0001: /*******************************************************************************
0002: * Copyright (c) 2000, 2007 IBM Corporation and others.
0003: * All rights reserved. This program and the accompanying materials
0004: * are made available under the terms of the Eclipse Public License v1.0
0005: * which accompanies this distribution, and is available at
0006: * http://www.eclipse.org/legal/epl-v10.html
0007: *
0008: * Contributors:
0009: * IBM Corporation - initial API and implementation
0010: *******************************************************************************/package org.eclipse.jdt.internal.compiler;
0011:
0012: import java.io.BufferedOutputStream;
0013: import java.io.File;
0014: import java.io.FileOutputStream;
0015: import java.io.IOException;
0016: import java.util.ArrayList;
0017: import java.util.Arrays;
0018: import java.util.Comparator;
0019: import java.util.HashSet;
0020: import java.util.Set;
0021: import java.util.StringTokenizer;
0022:
0023: import org.eclipse.jdt.core.compiler.CategorizedProblem;
0024: import org.eclipse.jdt.core.compiler.CharOperation;
0025: import org.eclipse.jdt.core.compiler.IProblem;
0026: import org.eclipse.jdt.internal.compiler.ast.ASTNode;
0027: import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
0028: import org.eclipse.jdt.internal.compiler.ast.Annotation;
0029: import org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration;
0030: import org.eclipse.jdt.internal.compiler.ast.Argument;
0031: import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
0032: import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
0033: import org.eclipse.jdt.internal.compiler.ast.Expression;
0034: import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
0035: import org.eclipse.jdt.internal.compiler.ast.MemberValuePair;
0036: import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
0037: import org.eclipse.jdt.internal.compiler.ast.NormalAnnotation;
0038: import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
0039: import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
0040: import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
0041: import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
0042: import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
0043: import org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants;
0044: import org.eclipse.jdt.internal.compiler.codegen.CodeStream;
0045: import org.eclipse.jdt.internal.compiler.codegen.ConstantPool;
0046: import org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel;
0047: import org.eclipse.jdt.internal.compiler.codegen.Opcodes;
0048: import org.eclipse.jdt.internal.compiler.codegen.StackMapFrame;
0049: import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream;
0050: import org.eclipse.jdt.internal.compiler.codegen.VerificationTypeInfo;
0051: import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.ExceptionMarker;
0052: import org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackMarker;
0053: import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
0054: import org.eclipse.jdt.internal.compiler.impl.Constant;
0055: import org.eclipse.jdt.internal.compiler.impl.StringConstant;
0056: import org.eclipse.jdt.internal.compiler.lookup.Binding;
0057: import org.eclipse.jdt.internal.compiler.lookup.FieldBinding;
0058: import org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding;
0059: import org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding;
0060: import org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment;
0061: import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
0062: import org.eclipse.jdt.internal.compiler.lookup.NestedTypeBinding;
0063: import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
0064: import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding;
0065: import org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding;
0066: import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding;
0067: import org.eclipse.jdt.internal.compiler.lookup.TagBits;
0068: import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
0069: import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
0070: import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
0071: import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities;
0072: import org.eclipse.jdt.internal.compiler.util.Messages;
0073: import org.eclipse.jdt.internal.compiler.util.Util;
0074:
0075: /**
0076: * Represents a class file wrapper on bytes, it is aware of its actual
0077: * type name.
0078: *
0079: * Public APIs are listed below:
0080: *
0081: * byte[] getBytes();
0082: * Answer the actual bytes of the class file
0083: *
0084: * char[][] getCompoundName();
0085: * Answer the compound name of the class file.
0086: * For example, {{java}, {util}, {Hashtable}}.
0087: *
0088: * byte[] getReducedBytes();
0089: * Answer a smaller byte format, which is only contains some structural
0090: * information. Those bytes are decodable with a regular class file reader,
0091: * such as DietClassFileReader
0092: */
0093: public class ClassFile implements TypeConstants, TypeIds {
0094:
0095: private byte[] bytes;
0096: public CodeStream codeStream;
0097: public ConstantPool constantPool;
0098:
0099: public int constantPoolOffset;
0100:
0101: // the header contains all the bytes till the end of the constant pool
0102: public byte[] contents;
0103:
0104: public int contentsOffset;
0105:
0106: protected boolean creatingProblemType;
0107:
0108: public ClassFile enclosingClassFile;
0109: public byte[] header;
0110: // that collection contains all the remaining bytes of the .class file
0111: public int headerOffset;
0112: public Set innerClassesBindings;
0113: public int methodCount;
0114: public int methodCountOffset;
0115: // pool managment
0116: public boolean isShared = false;
0117: // used to generate private access methods
0118: // debug and stack map attributes
0119: public int produceAttributes;
0120: public SourceTypeBinding referenceBinding;
0121: public long targetJDK;
0122: public static final int INITIAL_CONTENTS_SIZE = 400;
0123: public static final int INITIAL_HEADER_SIZE = 1500;
0124: public static final int INNER_CLASSES_SIZE = 5;
0125:
0126: /**
0127: * INTERNAL USE-ONLY
0128: * Build all the directories and subdirectories corresponding to the packages names
0129: * into the directory specified in parameters.
0130: *
0131: * outputPath is formed like:
0132: * c:\temp\ the last character is a file separator
0133: * relativeFileName is formed like:
0134: * java\lang\String.class *
0135: *
0136: * @param outputPath java.lang.String
0137: * @param relativeFileName java.lang.String
0138: * @return java.lang.String
0139: */
0140: public static String buildAllDirectoriesInto(String outputPath,
0141: String relativeFileName) throws IOException {
0142: char fileSeparatorChar = File.separatorChar;
0143: String fileSeparator = File.separator;
0144: File f;
0145: outputPath = outputPath.replace('/', fileSeparatorChar);
0146: // these could be optimized out if we normalized paths once and for
0147: // all
0148: relativeFileName = relativeFileName.replace('/',
0149: fileSeparatorChar);
0150: String outputDirPath, fileName;
0151: int separatorIndex = relativeFileName
0152: .lastIndexOf(fileSeparatorChar);
0153: if (separatorIndex == -1) {
0154: if (outputPath.endsWith(fileSeparator)) {
0155: outputDirPath = outputPath.substring(0, outputPath
0156: .length() - 1);
0157: fileName = outputPath + relativeFileName;
0158: } else {
0159: outputDirPath = outputPath;
0160: fileName = outputPath + fileSeparator
0161: + relativeFileName;
0162: }
0163: } else {
0164: if (outputPath.endsWith(fileSeparator)) {
0165: outputDirPath = outputPath
0166: + relativeFileName.substring(0, separatorIndex);
0167: fileName = outputPath + relativeFileName;
0168: } else {
0169: outputDirPath = outputPath + fileSeparator
0170: + relativeFileName.substring(0, separatorIndex);
0171: fileName = outputPath + fileSeparator
0172: + relativeFileName;
0173: }
0174: }
0175: f = new File(outputDirPath);
0176: f.mkdirs();
0177: if (f.isDirectory()) {
0178: return fileName;
0179: } else {
0180: // the directory creation failed for some reason - retry using
0181: // a slower algorithm so as to refine the diagnostic
0182: if (outputPath.endsWith(fileSeparator)) {
0183: outputPath = outputPath.substring(0, outputPath
0184: .length() - 1);
0185: }
0186: f = new File(outputPath);
0187: boolean checkFileType = false;
0188: if (f.exists()) {
0189: checkFileType = true; // pre-existed
0190: } else {
0191: // we have to create that directory
0192: if (!f.mkdirs()) {
0193: if (f.exists()) {
0194: // someone else created f -- need to check its type
0195: checkFileType = true;
0196: } else {
0197: // no one could create f -- complain
0198: throw new IOException(Messages.bind(
0199: Messages.output_notValidAll, f
0200: .getAbsolutePath()));
0201: }
0202: }
0203: }
0204: if (checkFileType) {
0205: if (!f.isDirectory()) {
0206: throw new IOException(Messages
0207: .bind(Messages.output_isFile, f
0208: .getAbsolutePath()));
0209: }
0210: }
0211: StringBuffer outDir = new StringBuffer(outputPath);
0212: outDir.append(fileSeparator);
0213: StringTokenizer tokenizer = new StringTokenizer(
0214: relativeFileName, fileSeparator);
0215: String token = tokenizer.nextToken();
0216: while (tokenizer.hasMoreTokens()) {
0217: f = new File(outDir.append(token).append(fileSeparator)
0218: .toString());
0219: checkFileType = false; // reset
0220: if (f.exists()) {
0221: checkFileType = true; // this is suboptimal, but it catches corner cases
0222: // in which a regular file pre-exists
0223: } else {
0224: // we have to create that directory
0225: if (!f.mkdir()) {
0226: if (f.exists()) {
0227: // someone else created f -- need to check its type
0228: checkFileType = true;
0229: } else {
0230: // no one could create f -- complain
0231: throw new IOException(Messages.bind(
0232: Messages.output_notValid,
0233: outDir.substring(outputPath
0234: .length() + 1, outDir
0235: .length() - 1), outputPath));
0236: }
0237: }
0238: }
0239: if (checkFileType) {
0240: if (!f.isDirectory()) {
0241: throw new IOException(Messages.bind(
0242: Messages.output_isFile, f
0243: .getAbsolutePath()));
0244: }
0245: }
0246: token = tokenizer.nextToken();
0247: }
0248: // token contains the last one
0249: return outDir.append(token).toString();
0250: }
0251: }
0252:
0253: /**
0254: * INTERNAL USE-ONLY
0255: * Request the creation of a ClassFile compatible representation of a problematic type
0256: *
0257: * @param typeDeclaration org.eclipse.jdt.internal.compiler.ast.TypeDeclaration
0258: * @param unitResult org.eclipse.jdt.internal.compiler.CompilationUnitResult
0259: */
0260: public static void createProblemType(
0261: TypeDeclaration typeDeclaration,
0262: CompilationResult unitResult) {
0263: SourceTypeBinding typeBinding = typeDeclaration.binding;
0264: ClassFile classFile = ClassFile.getNewInstance(typeBinding);
0265: classFile.initialize(typeBinding, null, true);
0266:
0267: if (typeBinding.hasMemberTypes()) {
0268: // see bug 180109
0269: ReferenceBinding[] members = typeBinding.memberTypes;
0270: for (int i = 0, l = members.length; i < l; i++)
0271: classFile.recordInnerClasses(members[i]);
0272: }
0273: // TODO (olivier) handle cases where a field cannot be generated (name too long)
0274: // TODO (olivier) handle too many methods
0275: // inner attributes
0276: if (typeBinding.isNestedType()) {
0277: classFile.recordInnerClasses(typeBinding);
0278: }
0279:
0280: // add its fields
0281: FieldBinding[] fields = typeBinding.fields();
0282: if ((fields != null) && (fields != Binding.NO_FIELDS)) {
0283: classFile.addFieldInfos();
0284: } else {
0285: // we have to set the number of fields to be equals to 0
0286: classFile.contents[classFile.contentsOffset++] = 0;
0287: classFile.contents[classFile.contentsOffset++] = 0;
0288: }
0289: // leave some space for the methodCount
0290: classFile.setForMethodInfos();
0291: // add its user defined methods
0292: int problemsLength;
0293: CategorizedProblem[] problems = unitResult.getErrors();
0294: if (problems == null) {
0295: problems = new CategorizedProblem[0];
0296: }
0297: CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length];
0298: System.arraycopy(problems, 0, problemsCopy, 0, problemsLength);
0299:
0300: AbstractMethodDeclaration[] methodDecls = typeDeclaration.methods;
0301: if (methodDecls != null) {
0302: if (typeBinding.isInterface()) {
0303: // we cannot create problem methods for an interface. So we have to generate a clinit
0304: // which should contain all the problem
0305: classFile.addProblemClinit(problemsCopy);
0306: for (int i = 0, length = methodDecls.length; i < length; i++) {
0307: AbstractMethodDeclaration methodDecl = methodDecls[i];
0308: MethodBinding method = methodDecl.binding;
0309: if (method == null || method.isConstructor())
0310: continue;
0311: classFile.addAbstractMethod(methodDecl, method);
0312: }
0313: } else {
0314: for (int i = 0, length = methodDecls.length; i < length; i++) {
0315: AbstractMethodDeclaration methodDecl = methodDecls[i];
0316: MethodBinding method = methodDecl.binding;
0317: if (method == null)
0318: continue;
0319: if (method.isConstructor()) {
0320: classFile.addProblemConstructor(methodDecl,
0321: method, problemsCopy);
0322: } else {
0323: classFile.addProblemMethod(methodDecl, method,
0324: problemsCopy);
0325: }
0326: }
0327: }
0328: // add abstract methods
0329: classFile.addDefaultAbstractMethods();
0330: }
0331:
0332: // propagate generation of (problem) member types
0333: if (typeDeclaration.memberTypes != null) {
0334: for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) {
0335: TypeDeclaration memberType = typeDeclaration.memberTypes[i];
0336: if (memberType.binding != null) {
0337: ClassFile.createProblemType(memberType, unitResult);
0338: }
0339: }
0340: }
0341: classFile.addAttributes();
0342: unitResult.record(typeBinding.constantPoolName(), classFile);
0343: }
0344:
0345: public static ClassFile getNewInstance(SourceTypeBinding typeBinding) {
0346: LookupEnvironment env = typeBinding.scope.environment();
0347: return env.classFilePool.acquire(typeBinding);
0348: }
0349:
0350: /**
0351: * INTERNAL USE-ONLY
0352: * outputPath is formed like:
0353: * c:\temp\ the last character is a file separator
0354: * relativeFileName is formed like:
0355: * java\lang\String.class
0356: * @param generatePackagesStructure a flag to know if the packages structure has to be generated.
0357: * @param outputPath the given output directory
0358: * @param relativeFileName the given relative file name
0359: * @param classFile the given classFile to write
0360: *
0361: */
0362: public static void writeToDisk(boolean generatePackagesStructure,
0363: String outputPath, String relativeFileName,
0364: ClassFile classFile) throws IOException {
0365:
0366: BufferedOutputStream output = null;
0367: if (generatePackagesStructure) {
0368: output = new BufferedOutputStream(new FileOutputStream(
0369: new File(buildAllDirectoriesInto(outputPath,
0370: relativeFileName))));
0371: } else {
0372: String fileName = null;
0373: char fileSeparatorChar = File.separatorChar;
0374: String fileSeparator = File.separator;
0375: // First we ensure that the outputPath exists
0376: outputPath = outputPath.replace('/', fileSeparatorChar);
0377: // To be able to pass the mkdirs() method we need to remove the extra file separator at the end of the outDir name
0378: int indexOfPackageSeparator = relativeFileName
0379: .lastIndexOf(fileSeparatorChar);
0380: if (indexOfPackageSeparator == -1) {
0381: if (outputPath.endsWith(fileSeparator)) {
0382: fileName = outputPath + relativeFileName;
0383: } else {
0384: fileName = outputPath + fileSeparator
0385: + relativeFileName;
0386: }
0387: } else {
0388: int length = relativeFileName.length();
0389: if (outputPath.endsWith(fileSeparator)) {
0390: fileName = outputPath
0391: + relativeFileName
0392: .substring(
0393: indexOfPackageSeparator + 1,
0394: length);
0395: } else {
0396: fileName = outputPath
0397: + fileSeparator
0398: + relativeFileName
0399: .substring(
0400: indexOfPackageSeparator + 1,
0401: length);
0402: }
0403: }
0404: output = new BufferedOutputStream(new FileOutputStream(
0405: new File(fileName)));
0406: }
0407: try {
0408: // if no IOException occured, output cannot be null
0409: output.write(classFile.header, 0, classFile.headerOffset);
0410: output.write(classFile.contents, 0,
0411: classFile.contentsOffset);
0412: output.flush();
0413: } catch (IOException e) {
0414: throw e;
0415: } finally {
0416: output.close();
0417: }
0418: }
0419:
0420: /**
0421: * INTERNAL USE-ONLY
0422: * This methods creates a new instance of the receiver.
0423: */
0424: protected ClassFile() {
0425: // default constructor for subclasses
0426: }
0427:
0428: public ClassFile(SourceTypeBinding typeBinding) {
0429: // default constructor for subclasses
0430: this .constantPool = new ConstantPool(this );
0431: final CompilerOptions options = typeBinding.scope
0432: .compilerOptions();
0433: this .targetJDK = options.targetJDK;
0434: this .produceAttributes = options.produceDebugAttributes;
0435: this .referenceBinding = typeBinding;
0436: if (this .targetJDK >= ClassFileConstants.JDK1_6) {
0437: this .produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE;
0438: this .codeStream = new StackMapFrameCodeStream(this );
0439: } else if (this .targetJDK == ClassFileConstants.CLDC_1_1) {
0440: this .targetJDK = ClassFileConstants.JDK1_1; // put back 45.3
0441: this .produceAttributes |= ClassFileConstants.ATTR_STACK_MAP;
0442: this .codeStream = new StackMapFrameCodeStream(this );
0443: } else {
0444: this .codeStream = new CodeStream(this );
0445: }
0446: this .initByteArrays();
0447: }
0448:
0449: /**
0450: * INTERNAL USE-ONLY
0451: * Generate the byte for a problem method info that correspond to a boggus method.
0452: *
0453: * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
0454: * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
0455: */
0456: public void addAbstractMethod(AbstractMethodDeclaration method,
0457: MethodBinding methodBinding) {
0458:
0459: // force the modifiers to be public and abstract
0460: methodBinding.modifiers = ClassFileConstants.AccPublic
0461: | ClassFileConstants.AccAbstract;
0462:
0463: this .generateMethodInfoHeader(methodBinding);
0464: int methodAttributeOffset = this .contentsOffset;
0465: int attributeNumber = this
0466: .generateMethodInfoAttribute(methodBinding);
0467: this .completeMethodInfo(methodAttributeOffset, attributeNumber);
0468: }
0469:
0470: /**
0471: * INTERNAL USE-ONLY
0472: * This methods generate all the attributes for the receiver.
0473: * For a class they could be:
0474: * - source file attribute
0475: * - inner classes attribute
0476: * - deprecated attribute
0477: */
0478: public void addAttributes() {
0479: // update the method count
0480: contents[methodCountOffset++] = (byte) (methodCount >> 8);
0481: contents[methodCountOffset] = (byte) methodCount;
0482:
0483: int attributeNumber = 0;
0484: // leave two bytes for the number of attributes and store the current offset
0485: int attributeOffset = contentsOffset;
0486: contentsOffset += 2;
0487:
0488: // source attribute
0489: if ((produceAttributes & ClassFileConstants.ATTR_SOURCE) != 0) {
0490: String fullFileName = new String(referenceBinding.scope
0491: .referenceCompilationUnit().getFileName());
0492: fullFileName = fullFileName.replace('\\', '/');
0493: int lastIndex = fullFileName.lastIndexOf('/');
0494: if (lastIndex != -1) {
0495: fullFileName = fullFileName.substring(lastIndex + 1,
0496: fullFileName.length());
0497: }
0498: // check that there is enough space to write all the bytes for the field info corresponding
0499: // to the @fieldBinding
0500: if (contentsOffset + 8 >= contents.length) {
0501: resizeContents(8);
0502: }
0503: int sourceAttributeNameIndex = constantPool
0504: .literalIndex(AttributeNamesConstants.SourceName);
0505: contents[contentsOffset++] = (byte) (sourceAttributeNameIndex >> 8);
0506: contents[contentsOffset++] = (byte) sourceAttributeNameIndex;
0507: // The length of a source file attribute is 2. This is a fixed-length
0508: // attribute
0509: contents[contentsOffset++] = 0;
0510: contents[contentsOffset++] = 0;
0511: contents[contentsOffset++] = 0;
0512: contents[contentsOffset++] = 2;
0513: // write the source file name
0514: int fileNameIndex = constantPool.literalIndex(fullFileName
0515: .toCharArray());
0516: contents[contentsOffset++] = (byte) (fileNameIndex >> 8);
0517: contents[contentsOffset++] = (byte) fileNameIndex;
0518: attributeNumber++;
0519: }
0520: // Deprecated attribute
0521: if (referenceBinding.isDeprecated()) {
0522: // check that there is enough space to write all the bytes for the field info corresponding
0523: // to the @fieldBinding
0524: if (contentsOffset + 6 >= contents.length) {
0525: resizeContents(6);
0526: }
0527: int deprecatedAttributeNameIndex = constantPool
0528: .literalIndex(AttributeNamesConstants.DeprecatedName);
0529: contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
0530: contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
0531: // the length of a deprecated attribute is equals to 0
0532: contents[contentsOffset++] = 0;
0533: contents[contentsOffset++] = 0;
0534: contents[contentsOffset++] = 0;
0535: contents[contentsOffset++] = 0;
0536: attributeNumber++;
0537: }
0538: // add signature attribute
0539: char[] genericSignature = referenceBinding.genericSignature();
0540: if (genericSignature != null) {
0541: // check that there is enough space to write all the bytes for the field info corresponding
0542: // to the @fieldBinding
0543: if (contentsOffset + 8 >= contents.length) {
0544: resizeContents(8);
0545: }
0546: int signatureAttributeNameIndex = constantPool
0547: .literalIndex(AttributeNamesConstants.SignatureName);
0548: contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
0549: contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
0550: // the length of a signature attribute is equals to 2
0551: contents[contentsOffset++] = 0;
0552: contents[contentsOffset++] = 0;
0553: contents[contentsOffset++] = 0;
0554: contents[contentsOffset++] = 2;
0555: int signatureIndex = constantPool
0556: .literalIndex(genericSignature);
0557: contents[contentsOffset++] = (byte) (signatureIndex >> 8);
0558: contents[contentsOffset++] = (byte) signatureIndex;
0559: attributeNumber++;
0560: }
0561: if (targetJDK >= ClassFileConstants.JDK1_5
0562: && this .referenceBinding.isNestedType()
0563: && !this .referenceBinding.isMemberType()) {
0564: // add enclosing method attribute (1.5 mode only)
0565: if (contentsOffset + 10 >= contents.length) {
0566: resizeContents(10);
0567: }
0568: int enclosingMethodAttributeNameIndex = constantPool
0569: .literalIndex(AttributeNamesConstants.EnclosingMethodName);
0570: contents[contentsOffset++] = (byte) (enclosingMethodAttributeNameIndex >> 8);
0571: contents[contentsOffset++] = (byte) enclosingMethodAttributeNameIndex;
0572: // the length of a signature attribute is equals to 2
0573: contents[contentsOffset++] = 0;
0574: contents[contentsOffset++] = 0;
0575: contents[contentsOffset++] = 0;
0576: contents[contentsOffset++] = 4;
0577:
0578: int enclosingTypeIndex = constantPool
0579: .literalIndexForType(this .referenceBinding
0580: .enclosingType().constantPoolName());
0581: contents[contentsOffset++] = (byte) (enclosingTypeIndex >> 8);
0582: contents[contentsOffset++] = (byte) enclosingTypeIndex;
0583: byte methodIndexByte1 = 0;
0584: byte methodIndexByte2 = 0;
0585: if (this .referenceBinding instanceof LocalTypeBinding) {
0586: MethodBinding methodBinding = ((LocalTypeBinding) this .referenceBinding).enclosingMethod;
0587: if (methodBinding != null) {
0588: int enclosingMethodIndex = constantPool
0589: .literalIndexForNameAndType(
0590: methodBinding.selector,
0591: methodBinding.signature(this ));
0592: methodIndexByte1 = (byte) (enclosingMethodIndex >> 8);
0593: methodIndexByte2 = (byte) enclosingMethodIndex;
0594: }
0595: }
0596: contents[contentsOffset++] = methodIndexByte1;
0597: contents[contentsOffset++] = methodIndexByte2;
0598: attributeNumber++;
0599: }
0600: if (this .targetJDK >= ClassFileConstants.JDK1_5
0601: && !this .creatingProblemType) {
0602: TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
0603: if (typeDeclaration != null) {
0604: final Annotation[] annotations = typeDeclaration.annotations;
0605: if (annotations != null) {
0606: attributeNumber += generateRuntimeAnnotations(annotations);
0607: }
0608: }
0609: }
0610:
0611: if (this .referenceBinding.isHierarchyInconsistent()) {
0612: // add an attribute for inconsistent hierarchy
0613: if (contentsOffset + 6 >= contents.length) {
0614: resizeContents(6);
0615: }
0616: int inconsistentHierarchyNameIndex = constantPool
0617: .literalIndex(AttributeNamesConstants.InconsistentHierarchy);
0618: contents[contentsOffset++] = (byte) (inconsistentHierarchyNameIndex >> 8);
0619: contents[contentsOffset++] = (byte) inconsistentHierarchyNameIndex;
0620: // the length of an inconsistent hierarchy attribute is equals to 0
0621: contents[contentsOffset++] = 0;
0622: contents[contentsOffset++] = 0;
0623: contents[contentsOffset++] = 0;
0624: contents[contentsOffset++] = 0;
0625: attributeNumber++;
0626: }
0627: // Inner class attribute
0628: int numberOfInnerClasses = this .innerClassesBindings == null ? 0
0629: : this .innerClassesBindings.size();
0630: if (numberOfInnerClasses != 0) {
0631: ReferenceBinding[] innerClasses = new ReferenceBinding[numberOfInnerClasses];
0632: this .innerClassesBindings.toArray(innerClasses);
0633: Arrays.sort(innerClasses, new Comparator() {
0634: public int compare(Object o1, Object o2) {
0635: TypeBinding binding1 = (TypeBinding) o1;
0636: TypeBinding binding2 = (TypeBinding) o2;
0637: return CharOperation.compareTo(binding1
0638: .constantPoolName(), binding2
0639: .constantPoolName());
0640: }
0641: });
0642: // Generate the inner class attribute
0643: int exSize = 8 * numberOfInnerClasses + 8;
0644: if (exSize + contentsOffset >= this .contents.length) {
0645: resizeContents(exSize);
0646: }
0647: // Now we now the size of the attribute and the number of entries
0648: // attribute name
0649: int attributeNameIndex = constantPool
0650: .literalIndex(AttributeNamesConstants.InnerClassName);
0651: contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
0652: contents[contentsOffset++] = (byte) attributeNameIndex;
0653: int value = (numberOfInnerClasses << 3) + 2;
0654: contents[contentsOffset++] = (byte) (value >> 24);
0655: contents[contentsOffset++] = (byte) (value >> 16);
0656: contents[contentsOffset++] = (byte) (value >> 8);
0657: contents[contentsOffset++] = (byte) value;
0658: contents[contentsOffset++] = (byte) (numberOfInnerClasses >> 8);
0659: contents[contentsOffset++] = (byte) numberOfInnerClasses;
0660: for (int i = 0; i < numberOfInnerClasses; i++) {
0661: ReferenceBinding innerClass = innerClasses[i];
0662: int accessFlags = innerClass.getAccessFlags();
0663: int innerClassIndex = constantPool
0664: .literalIndexForType(innerClass
0665: .constantPoolName());
0666: // inner class index
0667: contents[contentsOffset++] = (byte) (innerClassIndex >> 8);
0668: contents[contentsOffset++] = (byte) innerClassIndex;
0669: // outer class index: anonymous and local have no outer class index
0670: if (innerClass.isMemberType()) {
0671: // member or member of local
0672: int outerClassIndex = constantPool
0673: .literalIndexForType(innerClass
0674: .enclosingType().constantPoolName());
0675: contents[contentsOffset++] = (byte) (outerClassIndex >> 8);
0676: contents[contentsOffset++] = (byte) outerClassIndex;
0677: } else {
0678: // equals to 0 if the innerClass is not a member type
0679: contents[contentsOffset++] = 0;
0680: contents[contentsOffset++] = 0;
0681: }
0682: // name index
0683: if (!innerClass.isAnonymousType()) {
0684: int nameIndex = constantPool
0685: .literalIndex(innerClass.sourceName());
0686: contents[contentsOffset++] = (byte) (nameIndex >> 8);
0687: contents[contentsOffset++] = (byte) nameIndex;
0688: } else {
0689: // equals to 0 if the innerClass is an anonymous type
0690: contents[contentsOffset++] = 0;
0691: contents[contentsOffset++] = 0;
0692: }
0693: // access flag
0694: if (innerClass.isAnonymousType()) {
0695: accessFlags &= ~ClassFileConstants.AccFinal;
0696: } else if (innerClass.isMemberType()
0697: && innerClass.isInterface()) {
0698: accessFlags |= ClassFileConstants.AccStatic; // implicitely static
0699: }
0700: contents[contentsOffset++] = (byte) (accessFlags >> 8);
0701: contents[contentsOffset++] = (byte) accessFlags;
0702: }
0703: attributeNumber++;
0704: }
0705: // update the number of attributes
0706: if (attributeOffset + 2 >= this .contents.length) {
0707: resizeContents(2);
0708: }
0709: contents[attributeOffset++] = (byte) (attributeNumber >> 8);
0710: contents[attributeOffset] = (byte) attributeNumber;
0711:
0712: // resynchronize all offsets of the classfile
0713: header = constantPool.poolContent;
0714: headerOffset = constantPool.currentOffset;
0715: int constantPoolCount = constantPool.currentIndex;
0716: header[constantPoolOffset++] = (byte) (constantPoolCount >> 8);
0717: header[constantPoolOffset] = (byte) constantPoolCount;
0718: }
0719:
0720: /**
0721: * INTERNAL USE-ONLY
0722: * This methods generate all the default abstract method infos that correpond to
0723: * the abstract methods inherited from superinterfaces.
0724: */
0725: public void addDefaultAbstractMethods() { // default abstract methods
0726: MethodBinding[] defaultAbstractMethods = referenceBinding
0727: .getDefaultAbstractMethods();
0728: for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
0729: generateMethodInfoHeader(defaultAbstractMethods[i]);
0730: int methodAttributeOffset = contentsOffset;
0731: int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
0732: completeMethodInfo(methodAttributeOffset, attributeNumber);
0733: }
0734: }
0735:
0736: private int addFieldAttributes(FieldBinding fieldBinding,
0737: int fieldAttributeOffset) {
0738: int attributesNumber = 0;
0739: // 4.7.2 only static constant fields get a ConstantAttribute
0740: // Generate the constantValueAttribute
0741: Constant fieldConstant = fieldBinding.constant();
0742: if (fieldConstant != Constant.NotAConstant) {
0743: if (contentsOffset + 8 >= contents.length) {
0744: resizeContents(8);
0745: }
0746: // Now we generate the constant attribute corresponding to the fieldBinding
0747: int constantValueNameIndex = constantPool
0748: .literalIndex(AttributeNamesConstants.ConstantValueName);
0749: contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
0750: contents[contentsOffset++] = (byte) constantValueNameIndex;
0751: // The attribute length = 2 in case of a constantValue attribute
0752: contents[contentsOffset++] = 0;
0753: contents[contentsOffset++] = 0;
0754: contents[contentsOffset++] = 0;
0755: contents[contentsOffset++] = 2;
0756: attributesNumber++;
0757: // Need to add the constant_value_index
0758: switch (fieldConstant.typeID()) {
0759: case T_boolean:
0760: int booleanValueIndex = constantPool
0761: .literalIndex(fieldConstant.booleanValue() ? 1
0762: : 0);
0763: contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
0764: contents[contentsOffset++] = (byte) booleanValueIndex;
0765: break;
0766: case T_byte:
0767: case T_char:
0768: case T_int:
0769: case T_short:
0770: int integerValueIndex = constantPool
0771: .literalIndex(fieldConstant.intValue());
0772: contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
0773: contents[contentsOffset++] = (byte) integerValueIndex;
0774: break;
0775: case T_float:
0776: int floatValueIndex = constantPool
0777: .literalIndex(fieldConstant.floatValue());
0778: contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
0779: contents[contentsOffset++] = (byte) floatValueIndex;
0780: break;
0781: case T_double:
0782: int doubleValueIndex = constantPool
0783: .literalIndex(fieldConstant.doubleValue());
0784: contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
0785: contents[contentsOffset++] = (byte) doubleValueIndex;
0786: break;
0787: case T_long:
0788: int longValueIndex = constantPool
0789: .literalIndex(fieldConstant.longValue());
0790: contents[contentsOffset++] = (byte) (longValueIndex >> 8);
0791: contents[contentsOffset++] = (byte) longValueIndex;
0792: break;
0793: case T_JavaLangString:
0794: int stringValueIndex = constantPool
0795: .literalIndex(((StringConstant) fieldConstant)
0796: .stringValue());
0797: if (stringValueIndex == -1) {
0798: if (!creatingProblemType) {
0799: // report an error and abort: will lead to a problem type classfile creation
0800: TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
0801: FieldDeclaration[] fieldDecls = typeDeclaration.fields;
0802: for (int i = 0, max = fieldDecls.length; i < max; i++) {
0803: if (fieldDecls[i].binding == fieldBinding) {
0804: // problem should abort
0805: typeDeclaration.scope
0806: .problemReporter()
0807: .stringConstantIsExceedingUtf8Limit(
0808: fieldDecls[i]);
0809: }
0810: }
0811: } else {
0812: // already inside a problem type creation : no constant for this field
0813: contentsOffset = fieldAttributeOffset;
0814: }
0815: } else {
0816: contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
0817: contents[contentsOffset++] = (byte) stringValueIndex;
0818: }
0819: }
0820: }
0821: if (this .targetJDK < ClassFileConstants.JDK1_5
0822: && fieldBinding.isSynthetic()) {
0823: if (contentsOffset + 6 >= contents.length) {
0824: resizeContents(6);
0825: }
0826: int syntheticAttributeNameIndex = constantPool
0827: .literalIndex(AttributeNamesConstants.SyntheticName);
0828: contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
0829: contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
0830: // the length of a synthetic attribute is equals to 0
0831: contents[contentsOffset++] = 0;
0832: contents[contentsOffset++] = 0;
0833: contents[contentsOffset++] = 0;
0834: contents[contentsOffset++] = 0;
0835: attributesNumber++;
0836: }
0837: if (fieldBinding.isDeprecated()) {
0838: if (contentsOffset + 6 >= contents.length) {
0839: resizeContents(6);
0840: }
0841: int deprecatedAttributeNameIndex = constantPool
0842: .literalIndex(AttributeNamesConstants.DeprecatedName);
0843: contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
0844: contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
0845: // the length of a deprecated attribute is equals to 0
0846: contents[contentsOffset++] = 0;
0847: contents[contentsOffset++] = 0;
0848: contents[contentsOffset++] = 0;
0849: contents[contentsOffset++] = 0;
0850: attributesNumber++;
0851: }
0852: // add signature attribute
0853: char[] genericSignature = fieldBinding.genericSignature();
0854: if (genericSignature != null) {
0855: // check that there is enough space to write all the bytes for the field info corresponding
0856: // to the @fieldBinding
0857: if (contentsOffset + 8 >= contents.length) {
0858: resizeContents(8);
0859: }
0860: int signatureAttributeNameIndex = constantPool
0861: .literalIndex(AttributeNamesConstants.SignatureName);
0862: contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
0863: contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
0864: // the length of a signature attribute is equals to 2
0865: contents[contentsOffset++] = 0;
0866: contents[contentsOffset++] = 0;
0867: contents[contentsOffset++] = 0;
0868: contents[contentsOffset++] = 2;
0869: int signatureIndex = constantPool
0870: .literalIndex(genericSignature);
0871: contents[contentsOffset++] = (byte) (signatureIndex >> 8);
0872: contents[contentsOffset++] = (byte) signatureIndex;
0873: attributesNumber++;
0874: }
0875: if (this .targetJDK >= ClassFileConstants.JDK1_5
0876: && !this .creatingProblemType) {
0877: FieldDeclaration fieldDeclaration = fieldBinding
0878: .sourceField();
0879: if (fieldDeclaration != null) {
0880: Annotation[] annotations = fieldDeclaration.annotations;
0881: if (annotations != null) {
0882: attributesNumber += generateRuntimeAnnotations(annotations);
0883: }
0884: }
0885: }
0886: return attributesNumber;
0887: }
0888:
0889: /**
0890: * INTERNAL USE-ONLY
0891: * This methods generates the bytes for the given field binding
0892: * @param fieldBinding the given field binding
0893: */
0894: private void addFieldInfo(FieldBinding fieldBinding) {
0895: // check that there is enough space to write all the bytes for the field info corresponding
0896: // to the @fieldBinding
0897: if (contentsOffset + 8 >= contents.length) {
0898: resizeContents(8);
0899: }
0900: // Now we can generate all entries into the byte array
0901: // First the accessFlags
0902: int accessFlags = fieldBinding.getAccessFlags();
0903: if (targetJDK < ClassFileConstants.JDK1_5) {
0904: // pre 1.5, synthetic was an attribute, not a modifier
0905: accessFlags &= ~ClassFileConstants.AccSynthetic;
0906: }
0907: contents[contentsOffset++] = (byte) (accessFlags >> 8);
0908: contents[contentsOffset++] = (byte) accessFlags;
0909: // Then the nameIndex
0910: int nameIndex = constantPool.literalIndex(fieldBinding.name);
0911: contents[contentsOffset++] = (byte) (nameIndex >> 8);
0912: contents[contentsOffset++] = (byte) nameIndex;
0913: // Then the descriptorIndex
0914: int descriptorIndex = constantPool
0915: .literalIndex(fieldBinding.type);
0916: contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
0917: contents[contentsOffset++] = (byte) descriptorIndex;
0918: int fieldAttributeOffset = contentsOffset;
0919: int attributeNumber = 0;
0920: // leave some space for the number of attributes
0921: contentsOffset += 2;
0922: attributeNumber += addFieldAttributes(fieldBinding,
0923: fieldAttributeOffset);
0924: if (contentsOffset + 2 >= contents.length) {
0925: resizeContents(2);
0926: }
0927: contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8);
0928: contents[fieldAttributeOffset] = (byte) attributeNumber;
0929: }
0930:
0931: /**
0932: * INTERNAL USE-ONLY
0933: * This methods generate all the fields infos for the receiver.
0934: * This includes:
0935: * - a field info for each defined field of that class
0936: * - a field info for each synthetic field (e.g. this$0)
0937: */
0938: /**
0939: * INTERNAL USE-ONLY
0940: * This methods generate all the fields infos for the receiver.
0941: * This includes:
0942: * - a field info for each defined field of that class
0943: * - a field info for each synthetic field (e.g. this$0)
0944: */
0945: public void addFieldInfos() {
0946: SourceTypeBinding currentBinding = referenceBinding;
0947: FieldBinding[] syntheticFields = currentBinding
0948: .syntheticFields();
0949: int fieldCount = currentBinding.fieldCount()
0950: + (syntheticFields == null ? 0 : syntheticFields.length);
0951:
0952: // write the number of fields
0953: if (fieldCount > 0xFFFF) {
0954: referenceBinding.scope.problemReporter().tooManyFields(
0955: referenceBinding.scope.referenceType());
0956: }
0957: contents[contentsOffset++] = (byte) (fieldCount >> 8);
0958: contents[contentsOffset++] = (byte) fieldCount;
0959:
0960: FieldDeclaration[] fieldDecls = currentBinding.scope.referenceContext.fields;
0961: for (int i = 0, max = fieldDecls == null ? 0
0962: : fieldDecls.length; i < max; i++) {
0963: FieldDeclaration fieldDecl = fieldDecls[i];
0964: if (fieldDecl.binding != null) {
0965: addFieldInfo(fieldDecl.binding);
0966: }
0967: }
0968:
0969: if (syntheticFields != null) {
0970: for (int i = 0, max = syntheticFields.length; i < max; i++) {
0971: addFieldInfo(syntheticFields[i]);
0972: }
0973: }
0974: }
0975:
0976: private void addMissingAbstractProblemMethod(
0977: MethodDeclaration methodDeclaration,
0978: MethodBinding methodBinding, CategorizedProblem problem,
0979: CompilationResult compilationResult) {
0980: // always clear the strictfp/native/abstract bit for a problem method
0981: generateMethodInfoHeader(
0982: methodBinding,
0983: methodBinding.modifiers
0984: & ~(ClassFileConstants.AccStrictfp
0985: | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract));
0986: int methodAttributeOffset = contentsOffset;
0987: int attributeNumber = generateMethodInfoAttribute(methodBinding);
0988:
0989: // Code attribute
0990: attributeNumber++;
0991:
0992: int codeAttributeOffset = contentsOffset;
0993: generateCodeAttributeHeader();
0994: StringBuffer buffer = new StringBuffer(25);
0995: buffer.append("\t" + problem.getMessage() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
0996: buffer.insert(0, Messages.compilation_unresolvedProblem);
0997: String problemString = buffer.toString();
0998:
0999: codeStream.init(this );
1000: codeStream.preserveUnusedLocals = true;
1001: codeStream.initializeMaxLocals(methodBinding);
1002:
1003: // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
1004: codeStream.generateCodeAttributeForProblemMethod(problemString);
1005:
1006: completeCodeAttributeForMissingAbstractProblemMethod(
1007: methodBinding, codeAttributeOffset, compilationResult
1008: .getLineSeparatorPositions(), problem
1009: .getSourceLineNumber());
1010:
1011: completeMethodInfo(methodAttributeOffset, attributeNumber);
1012: }
1013:
1014: /**
1015: * INTERNAL USE-ONLY
1016: * Generate the byte for a problem clinit method info that correspond to a boggus method.
1017: *
1018: * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1019: */
1020: public void addProblemClinit(CategorizedProblem[] problems) {
1021: generateMethodInfoHeaderForClinit();
1022: // leave two spaces for the number of attributes
1023: contentsOffset -= 2;
1024: int attributeOffset = contentsOffset;
1025: contentsOffset += 2;
1026: int attributeNumber = 0;
1027:
1028: int codeAttributeOffset = contentsOffset;
1029: generateCodeAttributeHeader();
1030: codeStream.resetForProblemClinit(this );
1031: String problemString = ""; //$NON-NLS-1$
1032: int problemLine = 0;
1033: if (problems != null) {
1034: int max = problems.length;
1035: StringBuffer buffer = new StringBuffer(25);
1036: int count = 0;
1037: for (int i = 0; i < max; i++) {
1038: CategorizedProblem problem = problems[i];
1039: if ((problem != null) && (problem.isError())) {
1040: buffer.append("\t" + problem.getMessage() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
1041: count++;
1042: if (problemLine == 0) {
1043: problemLine = problem.getSourceLineNumber();
1044: }
1045: problems[i] = null;
1046: }
1047: } // insert the top line afterwards, once knowing how many problems we have to consider
1048: if (count > 1) {
1049: buffer.insert(0,
1050: Messages.compilation_unresolvedProblems);
1051: } else {
1052: buffer
1053: .insert(0,
1054: Messages.compilation_unresolvedProblem);
1055: }
1056: problemString = buffer.toString();
1057: }
1058:
1059: // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
1060: codeStream.generateCodeAttributeForProblemMethod(problemString);
1061: attributeNumber++; // code attribute
1062: completeCodeAttributeForClinit(codeAttributeOffset, problemLine);
1063: if (contentsOffset + 2 >= contents.length) {
1064: resizeContents(2);
1065: }
1066: contents[attributeOffset++] = (byte) (attributeNumber >> 8);
1067: contents[attributeOffset] = (byte) attributeNumber;
1068: }
1069:
1070: /**
1071: * INTERNAL USE-ONLY
1072: * Generate the byte for a problem method info that correspond to a boggus constructor.
1073: *
1074: * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
1075: * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
1076: * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1077: */
1078: public void addProblemConstructor(AbstractMethodDeclaration method,
1079: MethodBinding methodBinding, CategorizedProblem[] problems) {
1080:
1081: // always clear the strictfp/native/abstract bit for a problem method
1082: generateMethodInfoHeader(
1083: methodBinding,
1084: methodBinding.modifiers
1085: & ~(ClassFileConstants.AccStrictfp
1086: | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract));
1087: int methodAttributeOffset = contentsOffset;
1088: int attributeNumber = generateMethodInfoAttribute(
1089: methodBinding, true);
1090:
1091: // Code attribute
1092: attributeNumber++;
1093: int codeAttributeOffset = contentsOffset;
1094: generateCodeAttributeHeader();
1095: codeStream.reset(method, this );
1096: String problemString = ""; //$NON-NLS-1$
1097: int problemLine = 0;
1098: if (problems != null) {
1099: int max = problems.length;
1100: StringBuffer buffer = new StringBuffer(25);
1101: int count = 0;
1102: for (int i = 0; i < max; i++) {
1103: CategorizedProblem problem = problems[i];
1104: if ((problem != null) && (problem.isError())) {
1105: buffer.append("\t" + problem.getMessage() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
1106: count++;
1107: if (problemLine == 0) {
1108: problemLine = problem.getSourceLineNumber();
1109: }
1110: }
1111: } // insert the top line afterwards, once knowing how many problems we have to consider
1112: if (count > 1) {
1113: buffer.insert(0,
1114: Messages.compilation_unresolvedProblems);
1115: } else {
1116: buffer
1117: .insert(0,
1118: Messages.compilation_unresolvedProblem);
1119: }
1120: problemString = buffer.toString();
1121: }
1122:
1123: // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
1124: codeStream.generateCodeAttributeForProblemMethod(problemString);
1125: completeCodeAttributeForProblemMethod(
1126: method,
1127: methodBinding,
1128: codeAttributeOffset,
1129: ((SourceTypeBinding) methodBinding.declaringClass).scope
1130: .referenceCompilationUnit().compilationResult
1131: .getLineSeparatorPositions(), problemLine);
1132: completeMethodInfo(methodAttributeOffset, attributeNumber);
1133: }
1134:
1135: /**
1136: * INTERNAL USE-ONLY
1137: * Generate the byte for a problem method info that correspond to a boggus constructor.
1138: * Reset the position inside the contents byte array to the savedOffset.
1139: *
1140: * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
1141: * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
1142: * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1143: * @param savedOffset <CODE>int</CODE>
1144: */
1145: public void addProblemConstructor(AbstractMethodDeclaration method,
1146: MethodBinding methodBinding, CategorizedProblem[] problems,
1147: int savedOffset) {
1148: // we need to move back the contentsOffset to the value at the beginning of the method
1149: contentsOffset = savedOffset;
1150: methodCount--; // we need to remove the method that causes the problem
1151: addProblemConstructor(method, methodBinding, problems);
1152: }
1153:
1154: /**
1155: * INTERNAL USE-ONLY
1156: * Generate the byte for a problem method info that correspond to a boggus method.
1157: *
1158: * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
1159: * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
1160: * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1161: */
1162: public void addProblemMethod(AbstractMethodDeclaration method,
1163: MethodBinding methodBinding, CategorizedProblem[] problems) {
1164: if (methodBinding.isAbstract()
1165: && methodBinding.declaringClass.isInterface()) {
1166: method.abort(ProblemSeverities.AbortType, null);
1167: }
1168: // always clear the strictfp/native/abstract bit for a problem method
1169: generateMethodInfoHeader(
1170: methodBinding,
1171: methodBinding.modifiers
1172: & ~(ClassFileConstants.AccStrictfp
1173: | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract));
1174: int methodAttributeOffset = contentsOffset;
1175: int attributeNumber = generateMethodInfoAttribute(
1176: methodBinding, true);
1177:
1178: // Code attribute
1179: attributeNumber++;
1180:
1181: int codeAttributeOffset = contentsOffset;
1182: generateCodeAttributeHeader();
1183: codeStream.reset(method, this );
1184: String problemString = ""; //$NON-NLS-1$
1185: int problemLine = 0;
1186: if (problems != null) {
1187: int max = problems.length;
1188: StringBuffer buffer = new StringBuffer(25);
1189: int count = 0;
1190: for (int i = 0; i < max; i++) {
1191: CategorizedProblem problem = problems[i];
1192: if ((problem != null)
1193: && (problem.isError())
1194: && (problem.getSourceStart() >= method.declarationSourceStart)
1195: && (problem.getSourceEnd() <= method.declarationSourceEnd)) {
1196: buffer.append("\t" + problem.getMessage() + "\n"); //$NON-NLS-1$ //$NON-NLS-2$
1197: count++;
1198: if (problemLine == 0) {
1199: problemLine = problem.getSourceLineNumber();
1200: }
1201: problems[i] = null;
1202: }
1203: } // insert the top line afterwards, once knowing how many problems we have to consider
1204: if (count > 1) {
1205: buffer.insert(0,
1206: Messages.compilation_unresolvedProblems);
1207: } else {
1208: buffer
1209: .insert(0,
1210: Messages.compilation_unresolvedProblem);
1211: }
1212: problemString = buffer.toString();
1213: }
1214:
1215: // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "")
1216: codeStream.generateCodeAttributeForProblemMethod(problemString);
1217: completeCodeAttributeForProblemMethod(
1218: method,
1219: methodBinding,
1220: codeAttributeOffset,
1221: ((SourceTypeBinding) methodBinding.declaringClass).scope
1222: .referenceCompilationUnit().compilationResult
1223: .getLineSeparatorPositions(), problemLine);
1224: completeMethodInfo(methodAttributeOffset, attributeNumber);
1225: }
1226:
1227: /**
1228: * INTERNAL USE-ONLY
1229: * Generate the byte for a problem method info that correspond to a boggus method.
1230: * Reset the position inside the contents byte array to the savedOffset.
1231: *
1232: * @param method org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration
1233: * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding
1234: * @param problems org.eclipse.jdt.internal.compiler.problem.Problem[]
1235: * @param savedOffset <CODE>int</CODE>
1236: */
1237: public void addProblemMethod(AbstractMethodDeclaration method,
1238: MethodBinding methodBinding, CategorizedProblem[] problems,
1239: int savedOffset) {
1240: // we need to move back the contentsOffset to the value at the beginning of the method
1241: contentsOffset = savedOffset;
1242: methodCount--; // we need to remove the method that causes the problem
1243: addProblemMethod(method, methodBinding, problems);
1244: }
1245:
1246: /**
1247: * INTERNAL USE-ONLY
1248: * Generate the byte for all the special method infos.
1249: * They are:
1250: * - synthetic access methods
1251: * - default abstract methods
1252: */
1253: public void addSpecialMethods() {
1254:
1255: // add all methods (default abstract methods and synthetic)
1256:
1257: // default abstract methods
1258: generateMissingAbstractMethods(
1259: referenceBinding.scope.referenceType().missingAbstractMethods,
1260: referenceBinding.scope.referenceCompilationUnit().compilationResult);
1261:
1262: MethodBinding[] defaultAbstractMethods = this .referenceBinding
1263: .getDefaultAbstractMethods();
1264: for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) {
1265: generateMethodInfoHeader(defaultAbstractMethods[i]);
1266: int methodAttributeOffset = contentsOffset;
1267: int attributeNumber = generateMethodInfoAttribute(defaultAbstractMethods[i]);
1268: completeMethodInfo(methodAttributeOffset, attributeNumber);
1269: }
1270: // add synthetic methods infos
1271: SyntheticMethodBinding[] syntheticMethods = this .referenceBinding
1272: .syntheticMethods();
1273: if (syntheticMethods != null) {
1274: for (int i = 0, max = syntheticMethods.length; i < max; i++) {
1275: SyntheticMethodBinding syntheticMethod = syntheticMethods[i];
1276: switch (syntheticMethod.kind) {
1277: case SyntheticMethodBinding.FieldReadAccess:
1278: // generate a method info to emulate an reading access to
1279: // a non-accessible field
1280: addSyntheticFieldReadAccessMethod(syntheticMethod);
1281: break;
1282: case SyntheticMethodBinding.FieldWriteAccess:
1283: // generate a method info to emulate an writing access to
1284: // a non-accessible field
1285: addSyntheticFieldWriteAccessMethod(syntheticMethod);
1286: break;
1287: case SyntheticMethodBinding.MethodAccess:
1288: case SyntheticMethodBinding.SuperMethodAccess:
1289: case SyntheticMethodBinding.BridgeMethod:
1290: // generate a method info to emulate an access to a non-accessible method / super-method or bridge method
1291: addSyntheticMethodAccessMethod(syntheticMethod);
1292: break;
1293: case SyntheticMethodBinding.ConstructorAccess:
1294: // generate a method info to emulate an access to a non-accessible constructor
1295: addSyntheticConstructorAccessMethod(syntheticMethod);
1296: break;
1297: case SyntheticMethodBinding.EnumValues:
1298: // generate a method info to define <enum>#values()
1299: addSyntheticEnumValuesMethod(syntheticMethod);
1300: break;
1301: case SyntheticMethodBinding.EnumValueOf:
1302: // generate a method info to define <enum>#valueOf(String)
1303: addSyntheticEnumValueOfMethod(syntheticMethod);
1304: break;
1305: case SyntheticMethodBinding.SwitchTable:
1306: // generate a method info to define the switch table synthetic method
1307: addSyntheticSwitchTable(syntheticMethod);
1308: }
1309: }
1310: }
1311: }
1312:
1313: /**
1314: * INTERNAL USE-ONLY
1315: * Generate the bytes for a synthetic method that provides an access to a private constructor.
1316: *
1317: * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1318: */
1319: public void addSyntheticConstructorAccessMethod(
1320: SyntheticMethodBinding methodBinding) {
1321: generateMethodInfoHeader(methodBinding);
1322: int methodAttributeOffset = this .contentsOffset;
1323: // this will add exception attribute, synthetic attribute, deprecated attribute,...
1324: int attributeNumber = generateMethodInfoAttribute(methodBinding);
1325: // Code attribute
1326: int codeAttributeOffset = contentsOffset;
1327: attributeNumber++; // add code attribute
1328: generateCodeAttributeHeader();
1329: codeStream.init(this );
1330: codeStream
1331: .generateSyntheticBodyForConstructorAccess(methodBinding);
1332: completeCodeAttributeForSyntheticMethod(
1333: methodBinding,
1334: codeAttributeOffset,
1335: ((SourceTypeBinding) methodBinding.declaringClass).scope
1336: .referenceCompilationUnit().compilationResult
1337: .getLineSeparatorPositions());
1338: // update the number of attributes
1339: contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1340: contents[methodAttributeOffset] = (byte) attributeNumber;
1341: }
1342:
1343: /**
1344: * INTERNAL USE-ONLY
1345: * Generate the bytes for a synthetic method that implements Enum#valueOf(String) for a given enum type
1346: *
1347: * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1348: */
1349: public void addSyntheticEnumValueOfMethod(
1350: SyntheticMethodBinding methodBinding) {
1351: generateMethodInfoHeader(methodBinding);
1352: int methodAttributeOffset = this .contentsOffset;
1353: // this will add exception attribute, synthetic attribute, deprecated attribute,...
1354: int attributeNumber = generateMethodInfoAttribute(methodBinding);
1355: // Code attribute
1356: int codeAttributeOffset = contentsOffset;
1357: attributeNumber++; // add code attribute
1358: generateCodeAttributeHeader();
1359: codeStream.init(this );
1360: codeStream.generateSyntheticBodyForEnumValueOf(methodBinding);
1361: completeCodeAttributeForSyntheticMethod(
1362: methodBinding,
1363: codeAttributeOffset,
1364: ((SourceTypeBinding) methodBinding.declaringClass).scope
1365: .referenceCompilationUnit().compilationResult
1366: .getLineSeparatorPositions());
1367: // update the number of attributes
1368: contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1369: contents[methodAttributeOffset] = (byte) attributeNumber;
1370: }
1371:
1372: /**
1373: * INTERNAL USE-ONLY
1374: * Generate the bytes for a synthetic method that implements Enum#values() for a given enum type
1375: *
1376: * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1377: */
1378: public void addSyntheticEnumValuesMethod(
1379: SyntheticMethodBinding methodBinding) {
1380: generateMethodInfoHeader(methodBinding);
1381: int methodAttributeOffset = this .contentsOffset;
1382: // this will add exception attribute, synthetic attribute, deprecated attribute,...
1383: int attributeNumber = generateMethodInfoAttribute(methodBinding);
1384: // Code attribute
1385: int codeAttributeOffset = contentsOffset;
1386: attributeNumber++; // add code attribute
1387: generateCodeAttributeHeader();
1388: codeStream.init(this );
1389: codeStream.generateSyntheticBodyForEnumValues(methodBinding);
1390: completeCodeAttributeForSyntheticMethod(
1391: methodBinding,
1392: codeAttributeOffset,
1393: ((SourceTypeBinding) methodBinding.declaringClass).scope
1394: .referenceCompilationUnit().compilationResult
1395: .getLineSeparatorPositions());
1396: // update the number of attributes
1397: contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1398: contents[methodAttributeOffset] = (byte) attributeNumber;
1399: }
1400:
1401: /**
1402: * INTERNAL USE-ONLY
1403: * Generate the byte for a problem method info that correspond to a synthetic method that
1404: * generate an read access to a private field.
1405: *
1406: * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1407: */
1408: public void addSyntheticFieldReadAccessMethod(
1409: SyntheticMethodBinding methodBinding) {
1410: generateMethodInfoHeader(methodBinding);
1411: int methodAttributeOffset = this .contentsOffset;
1412: // this will add exception attribute, synthetic attribute, deprecated attribute,...
1413: int attributeNumber = generateMethodInfoAttribute(methodBinding);
1414: // Code attribute
1415: int codeAttributeOffset = contentsOffset;
1416: attributeNumber++; // add code attribute
1417: generateCodeAttributeHeader();
1418: codeStream.init(this );
1419: codeStream
1420: .generateSyntheticBodyForFieldReadAccess(methodBinding);
1421: completeCodeAttributeForSyntheticMethod(
1422: methodBinding,
1423: codeAttributeOffset,
1424: ((SourceTypeBinding) methodBinding.declaringClass).scope
1425: .referenceCompilationUnit().compilationResult
1426: .getLineSeparatorPositions());
1427: // update the number of attributes
1428: contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1429: contents[methodAttributeOffset] = (byte) attributeNumber;
1430: }
1431:
1432: /**
1433: * INTERNAL USE-ONLY
1434: * Generate the byte for a problem method info that correspond to a synthetic method that
1435: * generate an write access to a private field.
1436: *
1437: * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1438: */
1439: public void addSyntheticFieldWriteAccessMethod(
1440: SyntheticMethodBinding methodBinding) {
1441: generateMethodInfoHeader(methodBinding);
1442: int methodAttributeOffset = this .contentsOffset;
1443: // this will add exception attribute, synthetic attribute, deprecated attribute,...
1444: int attributeNumber = generateMethodInfoAttribute(methodBinding);
1445: // Code attribute
1446: int codeAttributeOffset = contentsOffset;
1447: attributeNumber++; // add code attribute
1448: generateCodeAttributeHeader();
1449: codeStream.init(this );
1450: codeStream
1451: .generateSyntheticBodyForFieldWriteAccess(methodBinding);
1452: completeCodeAttributeForSyntheticMethod(
1453: methodBinding,
1454: codeAttributeOffset,
1455: ((SourceTypeBinding) methodBinding.declaringClass).scope
1456: .referenceCompilationUnit().compilationResult
1457: .getLineSeparatorPositions());
1458: // update the number of attributes
1459: contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1460: contents[methodAttributeOffset] = (byte) attributeNumber;
1461: }
1462:
1463: /**
1464: * INTERNAL USE-ONLY
1465: * Generate the bytes for a synthetic method that provides access to a private method.
1466: *
1467: * @param methodBinding org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding
1468: */
1469: public void addSyntheticMethodAccessMethod(
1470: SyntheticMethodBinding methodBinding) {
1471: generateMethodInfoHeader(methodBinding);
1472: int methodAttributeOffset = this .contentsOffset;
1473: // this will add exception attribute, synthetic attribute, deprecated attribute,...
1474: int attributeNumber = generateMethodInfoAttribute(methodBinding);
1475: // Code attribute
1476: int codeAttributeOffset = contentsOffset;
1477: attributeNumber++; // add code attribute
1478: generateCodeAttributeHeader();
1479: codeStream.init(this );
1480: codeStream.generateSyntheticBodyForMethodAccess(methodBinding);
1481: completeCodeAttributeForSyntheticMethod(
1482: methodBinding,
1483: codeAttributeOffset,
1484: ((SourceTypeBinding) methodBinding.declaringClass).scope
1485: .referenceCompilationUnit().compilationResult
1486: .getLineSeparatorPositions());
1487: // update the number of attributes
1488: contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1489: contents[methodAttributeOffset] = (byte) attributeNumber;
1490: }
1491:
1492: public void addSyntheticSwitchTable(
1493: SyntheticMethodBinding methodBinding) {
1494: generateMethodInfoHeader(methodBinding);
1495: int methodAttributeOffset = this .contentsOffset;
1496: // this will add exception attribute, synthetic attribute, deprecated attribute,...
1497: int attributeNumber = generateMethodInfoAttribute(methodBinding);
1498: // Code attribute
1499: int codeAttributeOffset = contentsOffset;
1500: attributeNumber++; // add code attribute
1501: generateCodeAttributeHeader();
1502: codeStream.init(this );
1503: codeStream.generateSyntheticBodyForSwitchTable(methodBinding);
1504: completeCodeAttributeForSyntheticMethod(
1505: true,
1506: methodBinding,
1507: codeAttributeOffset,
1508: ((SourceTypeBinding) methodBinding.declaringClass).scope
1509: .referenceCompilationUnit().compilationResult
1510: .getLineSeparatorPositions());
1511: // update the number of attributes
1512: contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
1513: contents[methodAttributeOffset] = (byte) attributeNumber;
1514: }
1515:
1516: /**
1517: * INTERNAL USE-ONLY
1518: * That method completes the creation of the code attribute by setting
1519: * - the attribute_length
1520: * - max_stack
1521: * - max_locals
1522: * - code_length
1523: * - exception table
1524: * - and debug attributes if necessary.
1525: *
1526: * @param codeAttributeOffset <CODE>int</CODE>
1527: */
1528: public void completeCodeAttribute(int codeAttributeOffset) {
1529: // reinitialize the localContents with the byte modified by the code stream
1530: this .contents = codeStream.bCodeStream;
1531: int localContentsOffset = codeStream.classFileOffset;
1532: // codeAttributeOffset is the position inside localContents byte array before we started to write
1533: // any information about the codeAttribute
1534: // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
1535: // to get the right position, 6 for the max_stack etc...
1536: int code_length = codeStream.position;
1537: if (code_length > 65535) {
1538: codeStream.methodDeclaration.scope.problemReporter()
1539: .bytecodeExceeds64KLimit(
1540: codeStream.methodDeclaration);
1541: }
1542: if (localContentsOffset + 20 >= this .contents.length) {
1543: resizeContents(20);
1544: }
1545: int max_stack = codeStream.stackMax;
1546: this .contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
1547: this .contents[codeAttributeOffset + 7] = (byte) max_stack;
1548: int max_locals = codeStream.maxLocals;
1549: this .contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
1550: this .contents[codeAttributeOffset + 9] = (byte) max_locals;
1551: this .contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
1552: this .contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
1553: this .contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
1554: this .contents[codeAttributeOffset + 13] = (byte) code_length;
1555:
1556: boolean addStackMaps = (this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0;
1557: // write the exception table
1558: ExceptionLabel[] exceptionLabels = codeStream.exceptionLabels;
1559: int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous)
1560: for (int i = 0, length = codeStream.exceptionLabelsCounter; i < length; i++) {
1561: exceptionHandlersCount += codeStream.exceptionLabels[i].count / 2;
1562: }
1563: int exSize = exceptionHandlersCount * 8 + 2;
1564: if (exSize + localContentsOffset >= this .contents.length) {
1565: resizeContents(exSize);
1566: }
1567: // there is no exception table, so we need to offset by 2 the current offset and move
1568: // on the attribute generation
1569: this .contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8);
1570: this .contents[localContentsOffset++] = (byte) exceptionHandlersCount;
1571: for (int i = 0, max = codeStream.exceptionLabelsCounter; i < max; i++) {
1572: ExceptionLabel exceptionLabel = exceptionLabels[i];
1573: if (exceptionLabel != null) {
1574: int iRange = 0, maxRange = exceptionLabel.count;
1575: if ((maxRange & 1) != 0) {
1576: codeStream.methodDeclaration.scope
1577: .problemReporter()
1578: .abortDueToInternalError(
1579: Messages
1580: .bind(
1581: Messages.abort_invalidExceptionAttribute,
1582: new String(
1583: codeStream.methodDeclaration.selector)),
1584: codeStream.methodDeclaration);
1585: }
1586: while (iRange < maxRange) {
1587: int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
1588: this .contents[localContentsOffset++] = (byte) (start >> 8);
1589: this .contents[localContentsOffset++] = (byte) start;
1590: int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions
1591: this .contents[localContentsOffset++] = (byte) (end >> 8);
1592: this .contents[localContentsOffset++] = (byte) end;
1593: int handlerPC = exceptionLabel.position;
1594: if (addStackMaps) {
1595: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
1596: stackMapFrameCodeStream
1597: .addFramePosition(handlerPC);
1598: // stackMapFrameCodeStream.addExceptionMarker(handlerPC, exceptionLabel.exceptionType);
1599: }
1600: this .contents[localContentsOffset++] = (byte) (handlerPC >> 8);
1601: this .contents[localContentsOffset++] = (byte) handlerPC;
1602: if (exceptionLabel.exceptionType == null) {
1603: // any exception handler
1604: this .contents[localContentsOffset++] = 0;
1605: this .contents[localContentsOffset++] = 0;
1606: } else {
1607: int nameIndex;
1608: if (exceptionLabel.exceptionType == TypeBinding.NULL) {
1609: /* represents ClassNotFoundException, see class literal access*/
1610: nameIndex = constantPool
1611: .literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
1612: } else {
1613: nameIndex = constantPool
1614: .literalIndexForType(exceptionLabel.exceptionType);
1615: }
1616: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1617: this .contents[localContentsOffset++] = (byte) nameIndex;
1618: }
1619: }
1620: }
1621: }
1622: // debug attributes
1623: int codeAttributeAttributeOffset = localContentsOffset;
1624: int attributeNumber = 0;
1625: // leave two bytes for the attribute_length
1626: localContentsOffset += 2;
1627: if (localContentsOffset + 2 >= this .contents.length) {
1628: resizeContents(2);
1629: }
1630:
1631: // first we handle the linenumber attribute
1632: if ((this .produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
1633: /* Create and add the line number attribute (used for debugging)
1634: * Build the pairs of:
1635: * (bytecodePC lineNumber)
1636: * according to the table of start line indexes and the pcToSourceMap table
1637: * contained into the codestream
1638: */
1639: int[] pcToSourceMapTable;
1640: if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null)
1641: && (codeStream.pcToSourceMapSize != 0)) {
1642: int lineNumberNameIndex = constantPool
1643: .literalIndex(AttributeNamesConstants.LineNumberTableName);
1644: if (localContentsOffset + 8 >= this .contents.length) {
1645: resizeContents(8);
1646: }
1647: this .contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
1648: this .contents[localContentsOffset++] = (byte) lineNumberNameIndex;
1649: int lineNumberTableOffset = localContentsOffset;
1650: localContentsOffset += 6;
1651: // leave space for attribute_length and line_number_table_length
1652: int numberOfEntries = 0;
1653: int length = codeStream.pcToSourceMapSize;
1654: for (int i = 0; i < length;) {
1655: // write the entry
1656: if (localContentsOffset + 4 >= this .contents.length) {
1657: resizeContents(4);
1658: }
1659: int pc = pcToSourceMapTable[i++];
1660: this .contents[localContentsOffset++] = (byte) (pc >> 8);
1661: this .contents[localContentsOffset++] = (byte) pc;
1662: int lineNumber = pcToSourceMapTable[i++];
1663: this .contents[localContentsOffset++] = (byte) (lineNumber >> 8);
1664: this .contents[localContentsOffset++] = (byte) lineNumber;
1665: numberOfEntries++;
1666: }
1667: // now we change the size of the line number attribute
1668: int lineNumberAttr_length = numberOfEntries * 4 + 2;
1669: this .contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
1670: this .contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
1671: this .contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
1672: this .contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
1673: this .contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
1674: this .contents[lineNumberTableOffset++] = (byte) numberOfEntries;
1675: attributeNumber++;
1676: }
1677: }
1678: // then we do the local variable attribute
1679: if ((this .produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
1680: int numberOfEntries = 0;
1681: int localVariableNameIndex = constantPool
1682: .literalIndex(AttributeNamesConstants.LocalVariableTableName);
1683: final boolean methodDeclarationIsStatic = codeStream.methodDeclaration
1684: .isStatic();
1685: int maxOfEntries = 8 + 10 * (methodDeclarationIsStatic ? 0
1686: : 1);
1687: for (int i = 0; i < codeStream.allLocalsCounter; i++) {
1688: LocalVariableBinding localVariableBinding = codeStream.locals[i];
1689: maxOfEntries += 10 * localVariableBinding.initializationCount;
1690: }
1691: // reserve enough space
1692: if (localContentsOffset + maxOfEntries >= this .contents.length) {
1693: resizeContents(maxOfEntries);
1694: }
1695: this .contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
1696: this .contents[localContentsOffset++] = (byte) localVariableNameIndex;
1697: int localVariableTableOffset = localContentsOffset;
1698: // leave space for attribute_length and local_variable_table_length
1699: localContentsOffset += 6;
1700: int nameIndex;
1701: int descriptorIndex;
1702: SourceTypeBinding declaringClassBinding = null;
1703: if (!methodDeclarationIsStatic) {
1704: numberOfEntries++;
1705: this .contents[localContentsOffset++] = 0; // the startPC for this is always 0
1706: this .contents[localContentsOffset++] = 0;
1707: this .contents[localContentsOffset++] = (byte) (code_length >> 8);
1708: this .contents[localContentsOffset++] = (byte) code_length;
1709: nameIndex = constantPool
1710: .literalIndex(ConstantPool.This);
1711: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1712: this .contents[localContentsOffset++] = (byte) nameIndex;
1713: declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
1714: descriptorIndex = constantPool
1715: .literalIndex(declaringClassBinding.signature());
1716: this .contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1717: this .contents[localContentsOffset++] = (byte) descriptorIndex;
1718: this .contents[localContentsOffset++] = 0;// the resolved position for this is always 0
1719: this .contents[localContentsOffset++] = 0;
1720: }
1721: // used to remember the local variable with a generic type
1722: int genericLocalVariablesCounter = 0;
1723: LocalVariableBinding[] genericLocalVariables = null;
1724: int numberOfGenericEntries = 0;
1725:
1726: for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
1727: LocalVariableBinding localVariable = codeStream.locals[i];
1728: if (localVariable.declaration == null)
1729: continue;
1730: final TypeBinding localVariableTypeBinding = localVariable.type;
1731: boolean isParameterizedType = localVariableTypeBinding
1732: .isParameterizedType()
1733: || localVariableTypeBinding.isTypeVariable();
1734: if (localVariable.initializationCount != 0
1735: && isParameterizedType) {
1736: if (genericLocalVariables == null) {
1737: // we cannot have more than max locals
1738: genericLocalVariables = new LocalVariableBinding[max];
1739: }
1740: genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
1741: }
1742: for (int j = 0; j < localVariable.initializationCount; j++) {
1743: int startPC = localVariable.initializationPCs[j << 1];
1744: int endPC = localVariable.initializationPCs[(j << 1) + 1];
1745: if (startPC != endPC) { // only entries for non zero length
1746: if (endPC == -1) {
1747: localVariable.declaringScope
1748: .problemReporter()
1749: .abortDueToInternalError(
1750: Messages
1751: .bind(
1752: Messages.abort_invalidAttribute,
1753: new String(
1754: localVariable.name)),
1755: (ASTNode) localVariable.declaringScope
1756: .methodScope().referenceContext);
1757: }
1758: if (isParameterizedType) {
1759: numberOfGenericEntries++;
1760: }
1761: // now we can safely add the local entry
1762: numberOfEntries++;
1763: this .contents[localContentsOffset++] = (byte) (startPC >> 8);
1764: this .contents[localContentsOffset++] = (byte) startPC;
1765: int length = endPC - startPC;
1766: this .contents[localContentsOffset++] = (byte) (length >> 8);
1767: this .contents[localContentsOffset++] = (byte) length;
1768: nameIndex = constantPool
1769: .literalIndex(localVariable.name);
1770: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1771: this .contents[localContentsOffset++] = (byte) nameIndex;
1772: descriptorIndex = constantPool
1773: .literalIndex(localVariableTypeBinding
1774: .signature());
1775: this .contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1776: this .contents[localContentsOffset++] = (byte) descriptorIndex;
1777: int resolvedPosition = localVariable.resolvedPosition;
1778: this .contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
1779: this .contents[localContentsOffset++] = (byte) resolvedPosition;
1780: }
1781: }
1782: }
1783: int value = numberOfEntries * 10 + 2;
1784: this .contents[localVariableTableOffset++] = (byte) (value >> 24);
1785: this .contents[localVariableTableOffset++] = (byte) (value >> 16);
1786: this .contents[localVariableTableOffset++] = (byte) (value >> 8);
1787: this .contents[localVariableTableOffset++] = (byte) value;
1788: this .contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
1789: this .contents[localVariableTableOffset] = (byte) numberOfEntries;
1790: attributeNumber++;
1791:
1792: final boolean currentInstanceIsGeneric = !methodDeclarationIsStatic
1793: && declaringClassBinding != null
1794: && declaringClassBinding.typeVariables != Binding.NO_TYPE_VARIABLES;
1795: if (genericLocalVariablesCounter != 0
1796: || currentInstanceIsGeneric) {
1797: // add the local variable type table attribute
1798: numberOfGenericEntries += (currentInstanceIsGeneric ? 1
1799: : 0);
1800: maxOfEntries = 8 + numberOfGenericEntries * 10;
1801: // reserve enough space
1802: if (localContentsOffset + maxOfEntries >= this .contents.length) {
1803: resizeContents(maxOfEntries);
1804: }
1805: int localVariableTypeNameIndex = constantPool
1806: .literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
1807: this .contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
1808: this .contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
1809: value = numberOfGenericEntries * 10 + 2;
1810: this .contents[localContentsOffset++] = (byte) (value >> 24);
1811: this .contents[localContentsOffset++] = (byte) (value >> 16);
1812: this .contents[localContentsOffset++] = (byte) (value >> 8);
1813: this .contents[localContentsOffset++] = (byte) value;
1814: this .contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
1815: this .contents[localContentsOffset++] = (byte) numberOfGenericEntries;
1816: if (currentInstanceIsGeneric) {
1817: this .contents[localContentsOffset++] = 0; // the startPC for this is always 0
1818: this .contents[localContentsOffset++] = 0;
1819: this .contents[localContentsOffset++] = (byte) (code_length >> 8);
1820: this .contents[localContentsOffset++] = (byte) code_length;
1821: nameIndex = constantPool
1822: .literalIndex(ConstantPool.This);
1823: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1824: this .contents[localContentsOffset++] = (byte) nameIndex;
1825: descriptorIndex = constantPool
1826: .literalIndex(declaringClassBinding
1827: .genericTypeSignature());
1828: this .contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1829: this .contents[localContentsOffset++] = (byte) descriptorIndex;
1830: this .contents[localContentsOffset++] = 0;// the resolved position for this is always 0
1831: this .contents[localContentsOffset++] = 0;
1832: }
1833:
1834: for (int i = 0; i < genericLocalVariablesCounter; i++) {
1835: LocalVariableBinding localVariable = genericLocalVariables[i];
1836: for (int j = 0; j < localVariable.initializationCount; j++) {
1837: int startPC = localVariable.initializationPCs[j << 1];
1838: int endPC = localVariable.initializationPCs[(j << 1) + 1];
1839: if (startPC != endPC) {
1840: // only entries for non zero length
1841: // now we can safely add the local entry
1842: this .contents[localContentsOffset++] = (byte) (startPC >> 8);
1843: this .contents[localContentsOffset++] = (byte) startPC;
1844: int length = endPC - startPC;
1845: this .contents[localContentsOffset++] = (byte) (length >> 8);
1846: this .contents[localContentsOffset++] = (byte) length;
1847: nameIndex = constantPool
1848: .literalIndex(localVariable.name);
1849: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
1850: this .contents[localContentsOffset++] = (byte) nameIndex;
1851: descriptorIndex = constantPool
1852: .literalIndex(localVariable.type
1853: .genericTypeSignature());
1854: this .contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
1855: this .contents[localContentsOffset++] = (byte) descriptorIndex;
1856: int resolvedPosition = localVariable.resolvedPosition;
1857: this .contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
1858: this .contents[localContentsOffset++] = (byte) resolvedPosition;
1859: }
1860: }
1861: }
1862: attributeNumber++;
1863: }
1864: }
1865:
1866: if (addStackMaps) {
1867: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
1868: stackMapFrameCodeStream.removeFramePosition(code_length);
1869: if (stackMapFrameCodeStream.hasFramePositions()) {
1870: ArrayList frames = new ArrayList();
1871: traverse(this .codeStream.methodDeclaration.binding,
1872: max_locals, this .contents,
1873: codeAttributeOffset + 14, code_length, frames,
1874: false);
1875: int numberOfFrames = frames.size();
1876: if (numberOfFrames > 1) {
1877: int stackMapTableAttributeOffset = localContentsOffset;
1878: // add the stack map table attribute
1879: if (localContentsOffset + 8 >= this .contents.length) {
1880: resizeContents(8);
1881: }
1882: int stackMapTableAttributeNameIndex = constantPool
1883: .literalIndex(AttributeNamesConstants.StackMapTableName);
1884: this .contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
1885: this .contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
1886:
1887: int stackMapTableAttributeLengthOffset = localContentsOffset;
1888: // generate the attribute
1889: localContentsOffset += 4;
1890: if (localContentsOffset + 4 >= this .contents.length) {
1891: resizeContents(4);
1892: }
1893: int numberOfFramesOffset = localContentsOffset;
1894: localContentsOffset += 2;
1895: if (localContentsOffset + 2 >= this .contents.length) {
1896: resizeContents(2);
1897: }
1898: StackMapFrame currentFrame = (StackMapFrame) frames
1899: .get(0);
1900: StackMapFrame prevFrame = null;
1901: for (int j = 1; j < numberOfFrames; j++) {
1902: // select next frame
1903: prevFrame = currentFrame;
1904: currentFrame = (StackMapFrame) frames.get(j);
1905: // generate current frame
1906: // need to find differences between the current frame and the previous frame
1907: int offsetDelta = currentFrame
1908: .getOffsetDelta(prevFrame);
1909: switch (currentFrame.getFrameType(prevFrame)) {
1910: case StackMapFrame.APPEND_FRAME:
1911: if (localContentsOffset + 3 >= this .contents.length) {
1912: resizeContents(3);
1913: }
1914: int numberOfDifferentLocals = currentFrame
1915: .numberOfDifferentLocals(prevFrame);
1916: this .contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
1917: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
1918: this .contents[localContentsOffset++] = (byte) offsetDelta;
1919: int index = currentFrame
1920: .getIndexOfDifferentLocals(numberOfDifferentLocals);
1921: int numberOfLocals = currentFrame
1922: .getNumberOfLocals();
1923: for (int i = index; i < currentFrame.locals.length
1924: && numberOfDifferentLocals > 0; i++) {
1925: if (localContentsOffset + 6 >= this .contents.length) {
1926: resizeContents(6);
1927: }
1928: VerificationTypeInfo info = currentFrame.locals[i];
1929: if (info == null) {
1930: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
1931: } else {
1932: switch (info.id()) {
1933: case T_boolean:
1934: case T_byte:
1935: case T_char:
1936: case T_int:
1937: case T_short:
1938: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
1939: break;
1940: case T_float:
1941: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
1942: break;
1943: case T_long:
1944: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
1945: i++;
1946: break;
1947: case T_double:
1948: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
1949: i++;
1950: break;
1951: case T_null:
1952: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
1953: break;
1954: default:
1955: this .contents[localContentsOffset++] = (byte) info.tag;
1956: switch (info.tag) {
1957: case VerificationTypeInfo.ITEM_UNINITIALIZED:
1958: int offset = info.offset;
1959: this .contents[localContentsOffset++] = (byte) (offset >> 8);
1960: this .contents[localContentsOffset++] = (byte) offset;
1961: break;
1962: case VerificationTypeInfo.ITEM_OBJECT:
1963: int indexForType = constantPool
1964: .literalIndexForType(info
1965: .constantPoolName());
1966: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
1967: this .contents[localContentsOffset++] = (byte) indexForType;
1968: }
1969: }
1970: numberOfDifferentLocals--;
1971: }
1972: }
1973: break;
1974: case StackMapFrame.SAME_FRAME:
1975: if (localContentsOffset + 1 >= this .contents.length) {
1976: resizeContents(1);
1977: }
1978: this .contents[localContentsOffset++] = (byte) offsetDelta;
1979: break;
1980: case StackMapFrame.SAME_FRAME_EXTENDED:
1981: if (localContentsOffset + 3 >= this .contents.length) {
1982: resizeContents(3);
1983: }
1984: this .contents[localContentsOffset++] = (byte) 251;
1985: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
1986: this .contents[localContentsOffset++] = (byte) offsetDelta;
1987: break;
1988: case StackMapFrame.CHOP_FRAME:
1989: if (localContentsOffset + 3 >= this .contents.length) {
1990: resizeContents(3);
1991: }
1992: numberOfDifferentLocals = -currentFrame
1993: .numberOfDifferentLocals(prevFrame);
1994: this .contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
1995: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
1996: this .contents[localContentsOffset++] = (byte) offsetDelta;
1997: break;
1998: case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS:
1999: if (localContentsOffset + 4 >= this .contents.length) {
2000: resizeContents(4);
2001: }
2002: this .contents[localContentsOffset++] = (byte) (offsetDelta + 64);
2003: if (currentFrame.stackItems[0] == null) {
2004: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2005: } else {
2006: switch (currentFrame.stackItems[0].id()) {
2007: case T_boolean:
2008: case T_byte:
2009: case T_char:
2010: case T_int:
2011: case T_short:
2012: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2013: break;
2014: case T_float:
2015: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2016: break;
2017: case T_long:
2018: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2019: break;
2020: case T_double:
2021: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2022: break;
2023: case T_null:
2024: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2025: break;
2026: default:
2027: VerificationTypeInfo info = currentFrame.stackItems[0];
2028: byte tag = (byte) info.tag;
2029: this .contents[localContentsOffset++] = tag;
2030: switch (tag) {
2031: case VerificationTypeInfo.ITEM_UNINITIALIZED:
2032: int offset = info.offset;
2033: this .contents[localContentsOffset++] = (byte) (offset >> 8);
2034: this .contents[localContentsOffset++] = (byte) offset;
2035: break;
2036: case VerificationTypeInfo.ITEM_OBJECT:
2037: int indexForType = constantPool
2038: .literalIndexForType(info
2039: .constantPoolName());
2040: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
2041: this .contents[localContentsOffset++] = (byte) indexForType;
2042: }
2043: }
2044: }
2045: break;
2046: case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED:
2047: if (localContentsOffset + 6 >= this .contents.length) {
2048: resizeContents(6);
2049: }
2050: this .contents[localContentsOffset++] = (byte) 247;
2051: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2052: this .contents[localContentsOffset++] = (byte) offsetDelta;
2053: if (currentFrame.stackItems[0] == null) {
2054: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2055: } else {
2056: switch (currentFrame.stackItems[0].id()) {
2057: case T_boolean:
2058: case T_byte:
2059: case T_char:
2060: case T_int:
2061: case T_short:
2062: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2063: break;
2064: case T_float:
2065: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2066: break;
2067: case T_long:
2068: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2069: break;
2070: case T_double:
2071: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2072: break;
2073: case T_null:
2074: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2075: break;
2076: default:
2077: VerificationTypeInfo info = currentFrame.stackItems[0];
2078: byte tag = (byte) info.tag;
2079: this .contents[localContentsOffset++] = tag;
2080: switch (tag) {
2081: case VerificationTypeInfo.ITEM_UNINITIALIZED:
2082: int offset = info.offset;
2083: this .contents[localContentsOffset++] = (byte) (offset >> 8);
2084: this .contents[localContentsOffset++] = (byte) offset;
2085: break;
2086: case VerificationTypeInfo.ITEM_OBJECT:
2087: int indexForType = constantPool
2088: .literalIndexForType(info
2089: .constantPoolName());
2090: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
2091: this .contents[localContentsOffset++] = (byte) indexForType;
2092: }
2093: }
2094: }
2095: break;
2096: default:
2097: // FULL_FRAME
2098: if (localContentsOffset + 5 >= this .contents.length) {
2099: resizeContents(5);
2100: }
2101: this .contents[localContentsOffset++] = (byte) 255;
2102: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2103: this .contents[localContentsOffset++] = (byte) offsetDelta;
2104: int numberOfLocalOffset = localContentsOffset;
2105: localContentsOffset += 2; // leave two spots for number of locals
2106: int numberOfLocalEntries = 0;
2107: numberOfLocals = currentFrame
2108: .getNumberOfLocals();
2109: int numberOfEntries = 0;
2110: int localsLength = currentFrame.locals == null ? 0
2111: : currentFrame.locals.length;
2112: for (int i = 0; i < localsLength
2113: && numberOfLocalEntries < numberOfLocals; i++) {
2114: if (localContentsOffset + 3 >= this .contents.length) {
2115: resizeContents(3);
2116: }
2117: VerificationTypeInfo info = currentFrame.locals[i];
2118: if (info == null) {
2119: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2120: } else {
2121: switch (info.id()) {
2122: case T_boolean:
2123: case T_byte:
2124: case T_char:
2125: case T_int:
2126: case T_short:
2127: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2128: break;
2129: case T_float:
2130: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2131: break;
2132: case T_long:
2133: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2134: i++;
2135: break;
2136: case T_double:
2137: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2138: i++;
2139: break;
2140: case T_null:
2141: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2142: break;
2143: default:
2144: this .contents[localContentsOffset++] = (byte) info.tag;
2145: switch (info.tag) {
2146: case VerificationTypeInfo.ITEM_UNINITIALIZED:
2147: int offset = info.offset;
2148: this .contents[localContentsOffset++] = (byte) (offset >> 8);
2149: this .contents[localContentsOffset++] = (byte) offset;
2150: break;
2151: case VerificationTypeInfo.ITEM_OBJECT:
2152: int indexForType = constantPool
2153: .literalIndexForType(info
2154: .constantPoolName());
2155: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
2156: this .contents[localContentsOffset++] = (byte) indexForType;
2157: }
2158: }
2159: numberOfLocalEntries++;
2160: }
2161: numberOfEntries++;
2162: }
2163: if (localContentsOffset + 4 >= this .contents.length) {
2164: resizeContents(4);
2165: }
2166: this .contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
2167: this .contents[numberOfLocalOffset] = (byte) numberOfEntries;
2168: int numberOfStackItems = currentFrame.numberOfStackItems;
2169: this .contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
2170: this .contents[localContentsOffset++] = (byte) numberOfStackItems;
2171: for (int i = 0; i < numberOfStackItems; i++) {
2172: if (localContentsOffset + 3 >= this .contents.length) {
2173: resizeContents(3);
2174: }
2175: VerificationTypeInfo info = currentFrame.stackItems[i];
2176: if (info == null) {
2177: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2178: } else {
2179: switch (info.id()) {
2180: case T_boolean:
2181: case T_byte:
2182: case T_char:
2183: case T_int:
2184: case T_short:
2185: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2186: break;
2187: case T_float:
2188: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2189: break;
2190: case T_long:
2191: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2192: break;
2193: case T_double:
2194: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2195: break;
2196: case T_null:
2197: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2198: break;
2199: default:
2200: this .contents[localContentsOffset++] = (byte) info.tag;
2201: switch (info.tag) {
2202: case VerificationTypeInfo.ITEM_UNINITIALIZED:
2203: int offset = info.offset;
2204: this .contents[localContentsOffset++] = (byte) (offset >> 8);
2205: this .contents[localContentsOffset++] = (byte) offset;
2206: break;
2207: case VerificationTypeInfo.ITEM_OBJECT:
2208: int indexForType = constantPool
2209: .literalIndexForType(info
2210: .constantPoolName());
2211: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
2212: this .contents[localContentsOffset++] = (byte) indexForType;
2213: }
2214: }
2215: }
2216: }
2217: }
2218: }
2219:
2220: numberOfFrames--;
2221: if (numberOfFrames != 0) {
2222: this .contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
2223: this .contents[numberOfFramesOffset] = (byte) numberOfFrames;
2224:
2225: int attributeLength = localContentsOffset
2226: - stackMapTableAttributeLengthOffset
2227: - 4;
2228: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
2229: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
2230: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
2231: this .contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
2232: attributeNumber++;
2233: } else {
2234: localContentsOffset = stackMapTableAttributeOffset;
2235: }
2236: }
2237: }
2238: }
2239:
2240: if ((this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
2241: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
2242: stackMapFrameCodeStream.removeFramePosition(code_length);
2243: if (stackMapFrameCodeStream.hasFramePositions()) {
2244: ArrayList frames = new ArrayList();
2245: traverse(this .codeStream.methodDeclaration.binding,
2246: max_locals, this .contents,
2247: codeAttributeOffset + 14, code_length, frames,
2248: false);
2249: int numberOfFrames = frames.size();
2250: if (numberOfFrames > 1) {
2251: int stackMapTableAttributeOffset = localContentsOffset;
2252: // add the stack map table attribute
2253: if (localContentsOffset + 8 >= this .contents.length) {
2254: resizeContents(8);
2255: }
2256: int stackMapAttributeNameIndex = constantPool
2257: .literalIndex(AttributeNamesConstants.StackMapName);
2258: this .contents[localContentsOffset++] = (byte) (stackMapAttributeNameIndex >> 8);
2259: this .contents[localContentsOffset++] = (byte) stackMapAttributeNameIndex;
2260:
2261: int stackMapAttributeLengthOffset = localContentsOffset;
2262: // generate the attribute
2263: localContentsOffset += 4;
2264: if (localContentsOffset + 4 >= this .contents.length) {
2265: resizeContents(4);
2266: }
2267: int numberOfFramesOffset = localContentsOffset;
2268: localContentsOffset += 2;
2269: if (localContentsOffset + 2 >= this .contents.length) {
2270: resizeContents(2);
2271: }
2272: StackMapFrame currentFrame = (StackMapFrame) frames
2273: .get(0);
2274: for (int j = 1; j < numberOfFrames; j++) {
2275: // select next frame
2276: currentFrame = (StackMapFrame) frames.get(j);
2277: // generate current frame
2278: // need to find differences between the current frame and the previous frame
2279: int frameOffset = currentFrame.pc;
2280: // FULL_FRAME
2281: if (localContentsOffset + 5 >= this .contents.length) {
2282: resizeContents(5);
2283: }
2284: this .contents[localContentsOffset++] = (byte) (frameOffset >> 8);
2285: this .contents[localContentsOffset++] = (byte) frameOffset;
2286: int numberOfLocalOffset = localContentsOffset;
2287: localContentsOffset += 2; // leave two spots for number of locals
2288: int numberOfLocalEntries = 0;
2289: int numberOfLocals = currentFrame
2290: .getNumberOfLocals();
2291: int numberOfEntries = 0;
2292: int localsLength = currentFrame.locals == null ? 0
2293: : currentFrame.locals.length;
2294: for (int i = 0; i < localsLength
2295: && numberOfLocalEntries < numberOfLocals; i++) {
2296: if (localContentsOffset + 3 >= this .contents.length) {
2297: resizeContents(3);
2298: }
2299: VerificationTypeInfo info = currentFrame.locals[i];
2300: if (info == null) {
2301: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2302: } else {
2303: switch (info.id()) {
2304: case T_boolean:
2305: case T_byte:
2306: case T_char:
2307: case T_int:
2308: case T_short:
2309: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2310: break;
2311: case T_float:
2312: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2313: break;
2314: case T_long:
2315: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2316: i++;
2317: break;
2318: case T_double:
2319: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2320: i++;
2321: break;
2322: case T_null:
2323: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2324: break;
2325: default:
2326: this .contents[localContentsOffset++] = (byte) info.tag;
2327: switch (info.tag) {
2328: case VerificationTypeInfo.ITEM_UNINITIALIZED:
2329: int offset = info.offset;
2330: this .contents[localContentsOffset++] = (byte) (offset >> 8);
2331: this .contents[localContentsOffset++] = (byte) offset;
2332: break;
2333: case VerificationTypeInfo.ITEM_OBJECT:
2334: int indexForType = constantPool
2335: .literalIndexForType(info
2336: .constantPoolName());
2337: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
2338: this .contents[localContentsOffset++] = (byte) indexForType;
2339: }
2340: }
2341: numberOfLocalEntries++;
2342: }
2343: numberOfEntries++;
2344: }
2345: if (localContentsOffset + 4 >= this .contents.length) {
2346: resizeContents(4);
2347: }
2348: this .contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
2349: this .contents[numberOfLocalOffset] = (byte) numberOfEntries;
2350: int numberOfStackItems = currentFrame.numberOfStackItems;
2351: this .contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
2352: this .contents[localContentsOffset++] = (byte) numberOfStackItems;
2353: for (int i = 0; i < numberOfStackItems; i++) {
2354: if (localContentsOffset + 3 >= this .contents.length) {
2355: resizeContents(3);
2356: }
2357: VerificationTypeInfo info = currentFrame.stackItems[i];
2358: if (info == null) {
2359: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2360: } else {
2361: switch (info.id()) {
2362: case T_boolean:
2363: case T_byte:
2364: case T_char:
2365: case T_int:
2366: case T_short:
2367: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2368: break;
2369: case T_float:
2370: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2371: break;
2372: case T_long:
2373: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2374: break;
2375: case T_double:
2376: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2377: break;
2378: case T_null:
2379: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2380: break;
2381: default:
2382: this .contents[localContentsOffset++] = (byte) info.tag;
2383: switch (info.tag) {
2384: case VerificationTypeInfo.ITEM_UNINITIALIZED:
2385: int offset = info.offset;
2386: this .contents[localContentsOffset++] = (byte) (offset >> 8);
2387: this .contents[localContentsOffset++] = (byte) offset;
2388: break;
2389: case VerificationTypeInfo.ITEM_OBJECT:
2390: int indexForType = constantPool
2391: .literalIndexForType(info
2392: .constantPoolName());
2393: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
2394: this .contents[localContentsOffset++] = (byte) indexForType;
2395: }
2396: }
2397: }
2398: }
2399: }
2400:
2401: numberOfFrames--;
2402: if (numberOfFrames != 0) {
2403: this .contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
2404: this .contents[numberOfFramesOffset] = (byte) numberOfFrames;
2405:
2406: int attributeLength = localContentsOffset
2407: - stackMapAttributeLengthOffset - 4;
2408: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 24);
2409: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 16);
2410: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 8);
2411: this .contents[stackMapAttributeLengthOffset] = (byte) attributeLength;
2412: attributeNumber++;
2413: } else {
2414: localContentsOffset = stackMapTableAttributeOffset;
2415: }
2416: }
2417: }
2418: }
2419:
2420: this .contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
2421: this .contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
2422:
2423: // update the attribute length
2424: int codeAttributeLength = localContentsOffset
2425: - (codeAttributeOffset + 6);
2426: this .contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
2427: this .contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
2428: this .contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
2429: this .contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
2430: contentsOffset = localContentsOffset;
2431: }
2432:
2433: /**
2434: * INTERNAL USE-ONLY
2435: * That method completes the creation of the code attribute by setting
2436: * - the attribute_length
2437: * - max_stack
2438: * - max_locals
2439: * - code_length
2440: * - exception table
2441: * - and debug attributes if necessary.
2442: *
2443: * @param codeAttributeOffset <CODE>int</CODE>
2444: */
2445: public void completeCodeAttributeForClinit(int codeAttributeOffset) {
2446: // reinitialize the contents with the byte modified by the code stream
2447: this .contents = codeStream.bCodeStream;
2448: int localContentsOffset = codeStream.classFileOffset;
2449: // codeAttributeOffset is the position inside contents byte array before we started to write
2450: // any information about the codeAttribute
2451: // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
2452: // to get the right position, 6 for the max_stack etc...
2453: int code_length = codeStream.position;
2454: if (code_length > 65535) {
2455: codeStream.methodDeclaration.scope.problemReporter()
2456: .bytecodeExceeds64KLimit(
2457: codeStream.methodDeclaration.scope
2458: .referenceType());
2459: }
2460: if (localContentsOffset + 20 >= this .contents.length) {
2461: resizeContents(20);
2462: }
2463: int max_stack = codeStream.stackMax;
2464: this .contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
2465: this .contents[codeAttributeOffset + 7] = (byte) max_stack;
2466: int max_locals = codeStream.maxLocals;
2467: this .contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
2468: this .contents[codeAttributeOffset + 9] = (byte) max_locals;
2469: this .contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
2470: this .contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
2471: this .contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
2472: this .contents[codeAttributeOffset + 13] = (byte) code_length;
2473:
2474: boolean addStackMaps = (this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0;
2475: // write the exception table
2476: ExceptionLabel[] exceptionLabels = codeStream.exceptionLabels;
2477: int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous)
2478: for (int i = 0, length = codeStream.exceptionLabelsCounter; i < length; i++) {
2479: exceptionHandlersCount += codeStream.exceptionLabels[i].count / 2;
2480: }
2481: int exSize = exceptionHandlersCount * 8 + 2;
2482: if (exSize + localContentsOffset >= this .contents.length) {
2483: resizeContents(exSize);
2484: }
2485: // there is no exception table, so we need to offset by 2 the current offset and move
2486: // on the attribute generation
2487: this .contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8);
2488: this .contents[localContentsOffset++] = (byte) exceptionHandlersCount;
2489: for (int i = 0, max = codeStream.exceptionLabelsCounter; i < max; i++) {
2490: ExceptionLabel exceptionLabel = exceptionLabels[i];
2491: if (exceptionLabel != null) {
2492: int iRange = 0, maxRange = exceptionLabel.count;
2493: if ((maxRange & 1) != 0) {
2494: codeStream.methodDeclaration.scope
2495: .problemReporter()
2496: .abortDueToInternalError(
2497: Messages
2498: .bind(
2499: Messages.abort_invalidExceptionAttribute,
2500: new String(
2501: codeStream.methodDeclaration.selector)),
2502: codeStream.methodDeclaration);
2503: }
2504: while (iRange < maxRange) {
2505: int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
2506: this .contents[localContentsOffset++] = (byte) (start >> 8);
2507: this .contents[localContentsOffset++] = (byte) start;
2508: int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions
2509: this .contents[localContentsOffset++] = (byte) (end >> 8);
2510: this .contents[localContentsOffset++] = (byte) end;
2511: int handlerPC = exceptionLabel.position;
2512: this .contents[localContentsOffset++] = (byte) (handlerPC >> 8);
2513: this .contents[localContentsOffset++] = (byte) handlerPC;
2514: if (addStackMaps) {
2515: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
2516: stackMapFrameCodeStream
2517: .addFramePosition(handlerPC);
2518: // stackMapFrameCodeStream.addExceptionMarker(handlerPC, exceptionLabel.exceptionType);
2519: }
2520: if (exceptionLabel.exceptionType == null) {
2521: // any exception handler
2522: this .contents[localContentsOffset++] = 0;
2523: this .contents[localContentsOffset++] = 0;
2524: } else {
2525: int nameIndex;
2526: if (exceptionLabel.exceptionType == TypeBinding.NULL) {
2527: /* represents denote ClassNotFoundException, see class literal access*/
2528: nameIndex = constantPool
2529: .literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
2530: } else {
2531: nameIndex = constantPool
2532: .literalIndexForType(exceptionLabel.exceptionType);
2533: }
2534: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2535: this .contents[localContentsOffset++] = (byte) nameIndex;
2536: }
2537: }
2538: }
2539: }
2540: // debug attributes
2541: int codeAttributeAttributeOffset = localContentsOffset;
2542: int attributeNumber = 0;
2543: // leave two bytes for the attribute_length
2544: localContentsOffset += 2;
2545: if (localContentsOffset + 2 >= this .contents.length) {
2546: resizeContents(2);
2547: }
2548:
2549: // first we handle the linenumber attribute
2550: if ((this .produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
2551: /* Create and add the line number attribute (used for debugging)
2552: * Build the pairs of:
2553: * (bytecodePC lineNumber)
2554: * according to the table of start line indexes and the pcToSourceMap table
2555: * contained into the codestream
2556: */
2557: int[] pcToSourceMapTable;
2558: if (((pcToSourceMapTable = codeStream.pcToSourceMap) != null)
2559: && (codeStream.pcToSourceMapSize != 0)) {
2560: int lineNumberNameIndex = constantPool
2561: .literalIndex(AttributeNamesConstants.LineNumberTableName);
2562: if (localContentsOffset + 8 >= this .contents.length) {
2563: resizeContents(8);
2564: }
2565: this .contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
2566: this .contents[localContentsOffset++] = (byte) lineNumberNameIndex;
2567: int lineNumberTableOffset = localContentsOffset;
2568: localContentsOffset += 6;
2569: // leave space for attribute_length and line_number_table_length
2570: int numberOfEntries = 0;
2571: int length = codeStream.pcToSourceMapSize;
2572: for (int i = 0; i < length;) {
2573: // write the entry
2574: if (localContentsOffset + 4 >= this .contents.length) {
2575: resizeContents(4);
2576: }
2577: int pc = pcToSourceMapTable[i++];
2578: this .contents[localContentsOffset++] = (byte) (pc >> 8);
2579: this .contents[localContentsOffset++] = (byte) pc;
2580: int lineNumber = pcToSourceMapTable[i++];
2581: this .contents[localContentsOffset++] = (byte) (lineNumber >> 8);
2582: this .contents[localContentsOffset++] = (byte) lineNumber;
2583: numberOfEntries++;
2584: }
2585: // now we change the size of the line number attribute
2586: int lineNumberAttr_length = numberOfEntries * 4 + 2;
2587: this .contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24);
2588: this .contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16);
2589: this .contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8);
2590: this .contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length;
2591: this .contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8);
2592: this .contents[lineNumberTableOffset++] = (byte) numberOfEntries;
2593: attributeNumber++;
2594: }
2595: }
2596: // then we do the local variable attribute
2597: if ((this .produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
2598: int numberOfEntries = 0;
2599: // codeAttribute.addLocalVariableTableAttribute(this);
2600: if ((codeStream.pcToSourceMap != null)
2601: && (codeStream.pcToSourceMapSize != 0)) {
2602: int localVariableNameIndex = constantPool
2603: .literalIndex(AttributeNamesConstants.LocalVariableTableName);
2604: if (localContentsOffset + 8 >= this .contents.length) {
2605: resizeContents(8);
2606: }
2607: this .contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
2608: this .contents[localContentsOffset++] = (byte) localVariableNameIndex;
2609: int localVariableTableOffset = localContentsOffset;
2610: localContentsOffset += 6;
2611:
2612: // leave space for attribute_length and local_variable_table_length
2613: int nameIndex;
2614: int descriptorIndex;
2615:
2616: // used to remember the local variable with a generic type
2617: int genericLocalVariablesCounter = 0;
2618: LocalVariableBinding[] genericLocalVariables = null;
2619: int numberOfGenericEntries = 0;
2620:
2621: for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
2622: LocalVariableBinding localVariable = codeStream.locals[i];
2623: if (localVariable.declaration == null)
2624: continue;
2625: final TypeBinding localVariableTypeBinding = localVariable.type;
2626: boolean isParameterizedType = localVariableTypeBinding
2627: .isParameterizedType()
2628: || localVariableTypeBinding
2629: .isTypeVariable();
2630: if (localVariable.initializationCount != 0
2631: && isParameterizedType) {
2632: if (genericLocalVariables == null) {
2633: // we cannot have more than max locals
2634: genericLocalVariables = new LocalVariableBinding[max];
2635: }
2636: genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
2637: }
2638: for (int j = 0; j < localVariable.initializationCount; j++) {
2639: int startPC = localVariable.initializationPCs[j << 1];
2640: int endPC = localVariable.initializationPCs[(j << 1) + 1];
2641: if (startPC != endPC) { // only entries for non zero length
2642: if (endPC == -1) {
2643: localVariable.declaringScope
2644: .problemReporter()
2645: .abortDueToInternalError(
2646: Messages
2647: .bind(
2648: Messages.abort_invalidAttribute,
2649: new String(
2650: localVariable.name)),
2651: (ASTNode) localVariable.declaringScope
2652: .methodScope().referenceContext);
2653: }
2654: if (localContentsOffset + 10 >= this .contents.length) {
2655: resizeContents(10);
2656: }
2657: // now we can safely add the local entry
2658: numberOfEntries++;
2659: if (isParameterizedType) {
2660: numberOfGenericEntries++;
2661: }
2662: this .contents[localContentsOffset++] = (byte) (startPC >> 8);
2663: this .contents[localContentsOffset++] = (byte) startPC;
2664: int length = endPC - startPC;
2665: this .contents[localContentsOffset++] = (byte) (length >> 8);
2666: this .contents[localContentsOffset++] = (byte) length;
2667: nameIndex = constantPool
2668: .literalIndex(localVariable.name);
2669: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2670: this .contents[localContentsOffset++] = (byte) nameIndex;
2671: descriptorIndex = constantPool
2672: .literalIndex(localVariableTypeBinding
2673: .signature());
2674: this .contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2675: this .contents[localContentsOffset++] = (byte) descriptorIndex;
2676: int resolvedPosition = localVariable.resolvedPosition;
2677: this .contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
2678: this .contents[localContentsOffset++] = (byte) resolvedPosition;
2679: }
2680: }
2681: }
2682: int value = numberOfEntries * 10 + 2;
2683: this .contents[localVariableTableOffset++] = (byte) (value >> 24);
2684: this .contents[localVariableTableOffset++] = (byte) (value >> 16);
2685: this .contents[localVariableTableOffset++] = (byte) (value >> 8);
2686: this .contents[localVariableTableOffset++] = (byte) value;
2687: this .contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
2688: this .contents[localVariableTableOffset] = (byte) numberOfEntries;
2689: attributeNumber++;
2690:
2691: if (genericLocalVariablesCounter != 0) {
2692: // add the local variable type table attribute
2693: // reserve enough space
2694: int maxOfEntries = 8 + numberOfGenericEntries * 10;
2695:
2696: if (localContentsOffset + maxOfEntries >= this .contents.length) {
2697: resizeContents(maxOfEntries);
2698: }
2699: int localVariableTypeNameIndex = constantPool
2700: .literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
2701: this .contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
2702: this .contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
2703: value = numberOfGenericEntries * 10 + 2;
2704: this .contents[localContentsOffset++] = (byte) (value >> 24);
2705: this .contents[localContentsOffset++] = (byte) (value >> 16);
2706: this .contents[localContentsOffset++] = (byte) (value >> 8);
2707: this .contents[localContentsOffset++] = (byte) value;
2708: this .contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
2709: this .contents[localContentsOffset++] = (byte) numberOfGenericEntries;
2710: for (int i = 0; i < genericLocalVariablesCounter; i++) {
2711: LocalVariableBinding localVariable = genericLocalVariables[i];
2712: for (int j = 0; j < localVariable.initializationCount; j++) {
2713: int startPC = localVariable.initializationPCs[j << 1];
2714: int endPC = localVariable.initializationPCs[(j << 1) + 1];
2715: if (startPC != endPC) { // only entries for non zero length
2716: // now we can safely add the local entry
2717: this .contents[localContentsOffset++] = (byte) (startPC >> 8);
2718: this .contents[localContentsOffset++] = (byte) startPC;
2719: int length = endPC - startPC;
2720: this .contents[localContentsOffset++] = (byte) (length >> 8);
2721: this .contents[localContentsOffset++] = (byte) length;
2722: nameIndex = constantPool
2723: .literalIndex(localVariable.name);
2724: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
2725: this .contents[localContentsOffset++] = (byte) nameIndex;
2726: descriptorIndex = constantPool
2727: .literalIndex(localVariable.type
2728: .genericTypeSignature());
2729: this .contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
2730: this .contents[localContentsOffset++] = (byte) descriptorIndex;
2731: int resolvedPosition = localVariable.resolvedPosition;
2732: this .contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
2733: this .contents[localContentsOffset++] = (byte) resolvedPosition;
2734: }
2735: }
2736: }
2737: attributeNumber++;
2738: }
2739: }
2740: }
2741:
2742: if ((this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) {
2743: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
2744: stackMapFrameCodeStream.removeFramePosition(code_length);
2745: if (stackMapFrameCodeStream.hasFramePositions()) {
2746: ArrayList frames = new ArrayList();
2747: traverse(null, max_locals, this .contents,
2748: codeAttributeOffset + 14, code_length, frames,
2749: true);
2750: int numberOfFrames = frames.size();
2751: if (numberOfFrames > 1) {
2752: int stackMapTableAttributeOffset = localContentsOffset;
2753: // add the stack map table attribute
2754: if (localContentsOffset + 8 >= this .contents.length) {
2755: resizeContents(8);
2756: }
2757: int stackMapTableAttributeNameIndex = constantPool
2758: .literalIndex(AttributeNamesConstants.StackMapTableName);
2759: this .contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
2760: this .contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
2761:
2762: int stackMapTableAttributeLengthOffset = localContentsOffset;
2763: // generate the attribute
2764: localContentsOffset += 4;
2765: if (localContentsOffset + 4 >= this .contents.length) {
2766: resizeContents(4);
2767: }
2768: int numberOfFramesOffset = localContentsOffset;
2769: localContentsOffset += 2;
2770: if (localContentsOffset + 2 >= this .contents.length) {
2771: resizeContents(2);
2772: }
2773: StackMapFrame currentFrame = (StackMapFrame) frames
2774: .get(0);
2775: StackMapFrame prevFrame = null;
2776: for (int j = 1; j < numberOfFrames; j++) {
2777: // select next frame
2778: prevFrame = currentFrame;
2779: currentFrame = (StackMapFrame) frames.get(j);
2780: // generate current frame
2781: // need to find differences between the current frame and the previous frame
2782: int offsetDelta = currentFrame
2783: .getOffsetDelta(prevFrame);
2784: switch (currentFrame.getFrameType(prevFrame)) {
2785: case StackMapFrame.APPEND_FRAME:
2786: if (localContentsOffset + 3 >= this .contents.length) {
2787: resizeContents(3);
2788: }
2789: int numberOfDifferentLocals = currentFrame
2790: .numberOfDifferentLocals(prevFrame);
2791: this .contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
2792: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2793: this .contents[localContentsOffset++] = (byte) offsetDelta;
2794: int index = currentFrame
2795: .getIndexOfDifferentLocals(numberOfDifferentLocals);
2796: int numberOfLocals = currentFrame
2797: .getNumberOfLocals();
2798: for (int i = index; i < currentFrame.locals.length
2799: && numberOfDifferentLocals > 0; i++) {
2800: if (localContentsOffset + 6 >= this .contents.length) {
2801: resizeContents(6);
2802: }
2803: VerificationTypeInfo info = currentFrame.locals[i];
2804: if (info == null) {
2805: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2806: } else {
2807: switch (info.id()) {
2808: case T_boolean:
2809: case T_byte:
2810: case T_char:
2811: case T_int:
2812: case T_short:
2813: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2814: break;
2815: case T_float:
2816: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2817: break;
2818: case T_long:
2819: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2820: i++;
2821: break;
2822: case T_double:
2823: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2824: i++;
2825: break;
2826: case T_null:
2827: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2828: break;
2829: default:
2830: this .contents[localContentsOffset++] = (byte) info.tag;
2831: switch (info.tag) {
2832: case VerificationTypeInfo.ITEM_UNINITIALIZED:
2833: int offset = info.offset;
2834: this .contents[localContentsOffset++] = (byte) (offset >> 8);
2835: this .contents[localContentsOffset++] = (byte) offset;
2836: break;
2837: case VerificationTypeInfo.ITEM_OBJECT:
2838: int indexForType = constantPool
2839: .literalIndexForType(info
2840: .constantPoolName());
2841: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
2842: this .contents[localContentsOffset++] = (byte) indexForType;
2843: }
2844: }
2845: numberOfDifferentLocals--;
2846: }
2847: }
2848: break;
2849: case StackMapFrame.SAME_FRAME:
2850: if (localContentsOffset + 1 >= this .contents.length) {
2851: resizeContents(1);
2852: }
2853: this .contents[localContentsOffset++] = (byte) offsetDelta;
2854: break;
2855: case StackMapFrame.SAME_FRAME_EXTENDED:
2856: if (localContentsOffset + 3 >= this .contents.length) {
2857: resizeContents(3);
2858: }
2859: this .contents[localContentsOffset++] = (byte) 251;
2860: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2861: this .contents[localContentsOffset++] = (byte) offsetDelta;
2862: break;
2863: case StackMapFrame.CHOP_FRAME:
2864: if (localContentsOffset + 3 >= this .contents.length) {
2865: resizeContents(3);
2866: }
2867: numberOfDifferentLocals = -currentFrame
2868: .numberOfDifferentLocals(prevFrame);
2869: this .contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
2870: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2871: this .contents[localContentsOffset++] = (byte) offsetDelta;
2872: break;
2873: case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS:
2874: if (localContentsOffset + 4 >= this .contents.length) {
2875: resizeContents(4);
2876: }
2877: this .contents[localContentsOffset++] = (byte) (offsetDelta + 64);
2878: if (currentFrame.stackItems[0] == null) {
2879: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2880: } else {
2881: switch (currentFrame.stackItems[0].id()) {
2882: case T_boolean:
2883: case T_byte:
2884: case T_char:
2885: case T_int:
2886: case T_short:
2887: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2888: break;
2889: case T_float:
2890: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2891: break;
2892: case T_long:
2893: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2894: break;
2895: case T_double:
2896: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2897: break;
2898: case T_null:
2899: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2900: break;
2901: default:
2902: VerificationTypeInfo info = currentFrame.stackItems[0];
2903: byte tag = (byte) info.tag;
2904: this .contents[localContentsOffset++] = tag;
2905: switch (tag) {
2906: case VerificationTypeInfo.ITEM_UNINITIALIZED:
2907: int offset = info.offset;
2908: this .contents[localContentsOffset++] = (byte) (offset >> 8);
2909: this .contents[localContentsOffset++] = (byte) offset;
2910: break;
2911: case VerificationTypeInfo.ITEM_OBJECT:
2912: int indexForType = constantPool
2913: .literalIndexForType(info
2914: .constantPoolName());
2915: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
2916: this .contents[localContentsOffset++] = (byte) indexForType;
2917: }
2918: }
2919: }
2920: break;
2921: case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED:
2922: if (localContentsOffset + 6 >= this .contents.length) {
2923: resizeContents(6);
2924: }
2925: this .contents[localContentsOffset++] = (byte) 247;
2926: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2927: this .contents[localContentsOffset++] = (byte) offsetDelta;
2928: if (currentFrame.stackItems[0] == null) {
2929: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2930: } else {
2931: switch (currentFrame.stackItems[0].id()) {
2932: case T_boolean:
2933: case T_byte:
2934: case T_char:
2935: case T_int:
2936: case T_short:
2937: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
2938: break;
2939: case T_float:
2940: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
2941: break;
2942: case T_long:
2943: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
2944: break;
2945: case T_double:
2946: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
2947: break;
2948: case T_null:
2949: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
2950: break;
2951: default:
2952: VerificationTypeInfo info = currentFrame.stackItems[0];
2953: byte tag = (byte) info.tag;
2954: this .contents[localContentsOffset++] = tag;
2955: switch (tag) {
2956: case VerificationTypeInfo.ITEM_UNINITIALIZED:
2957: int offset = info.offset;
2958: this .contents[localContentsOffset++] = (byte) (offset >> 8);
2959: this .contents[localContentsOffset++] = (byte) offset;
2960: break;
2961: case VerificationTypeInfo.ITEM_OBJECT:
2962: int indexForType = constantPool
2963: .literalIndexForType(info
2964: .constantPoolName());
2965: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
2966: this .contents[localContentsOffset++] = (byte) indexForType;
2967: }
2968: }
2969: }
2970: break;
2971: default:
2972: // FULL_FRAME
2973: if (localContentsOffset + 5 >= this .contents.length) {
2974: resizeContents(5);
2975: }
2976: this .contents[localContentsOffset++] = (byte) 255;
2977: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
2978: this .contents[localContentsOffset++] = (byte) offsetDelta;
2979: int numberOfLocalOffset = localContentsOffset;
2980: localContentsOffset += 2; // leave two spots for number of locals
2981: int numberOfLocalEntries = 0;
2982: numberOfLocals = currentFrame
2983: .getNumberOfLocals();
2984: int numberOfEntries = 0;
2985: int localsLength = currentFrame.locals == null ? 0
2986: : currentFrame.locals.length;
2987: for (int i = 0; i < localsLength
2988: && numberOfLocalEntries < numberOfLocals; i++) {
2989: if (localContentsOffset + 3 >= this .contents.length) {
2990: resizeContents(3);
2991: }
2992: VerificationTypeInfo info = currentFrame.locals[i];
2993: if (info == null) {
2994: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
2995: } else {
2996: switch (info.id()) {
2997: case T_boolean:
2998: case T_byte:
2999: case T_char:
3000: case T_int:
3001: case T_short:
3002: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3003: break;
3004: case T_float:
3005: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3006: break;
3007: case T_long:
3008: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3009: i++;
3010: break;
3011: case T_double:
3012: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3013: i++;
3014: break;
3015: case T_null:
3016: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3017: break;
3018: default:
3019: this .contents[localContentsOffset++] = (byte) info.tag;
3020: switch (info.tag) {
3021: case VerificationTypeInfo.ITEM_UNINITIALIZED:
3022: int offset = info.offset;
3023: this .contents[localContentsOffset++] = (byte) (offset >> 8);
3024: this .contents[localContentsOffset++] = (byte) offset;
3025: break;
3026: case VerificationTypeInfo.ITEM_OBJECT:
3027: int indexForType = constantPool
3028: .literalIndexForType(info
3029: .constantPoolName());
3030: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
3031: this .contents[localContentsOffset++] = (byte) indexForType;
3032: }
3033: }
3034: numberOfLocalEntries++;
3035: }
3036: numberOfEntries++;
3037: }
3038: if (localContentsOffset + 4 >= this .contents.length) {
3039: resizeContents(4);
3040: }
3041: this .contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
3042: this .contents[numberOfLocalOffset] = (byte) numberOfEntries;
3043: int numberOfStackItems = currentFrame.numberOfStackItems;
3044: this .contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
3045: this .contents[localContentsOffset++] = (byte) numberOfStackItems;
3046: for (int i = 0; i < numberOfStackItems; i++) {
3047: if (localContentsOffset + 3 >= this .contents.length) {
3048: resizeContents(3);
3049: }
3050: VerificationTypeInfo info = currentFrame.stackItems[i];
3051: if (info == null) {
3052: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3053: } else {
3054: switch (info.id()) {
3055: case T_boolean:
3056: case T_byte:
3057: case T_char:
3058: case T_int:
3059: case T_short:
3060: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3061: break;
3062: case T_float:
3063: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3064: break;
3065: case T_long:
3066: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3067: break;
3068: case T_double:
3069: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3070: break;
3071: case T_null:
3072: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3073: break;
3074: default:
3075: this .contents[localContentsOffset++] = (byte) info.tag;
3076: switch (info.tag) {
3077: case VerificationTypeInfo.ITEM_UNINITIALIZED:
3078: int offset = info.offset;
3079: this .contents[localContentsOffset++] = (byte) (offset >> 8);
3080: this .contents[localContentsOffset++] = (byte) offset;
3081: break;
3082: case VerificationTypeInfo.ITEM_OBJECT:
3083: int indexForType = constantPool
3084: .literalIndexForType(info
3085: .constantPoolName());
3086: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
3087: this .contents[localContentsOffset++] = (byte) indexForType;
3088: }
3089: }
3090: }
3091: }
3092: }
3093: }
3094:
3095: numberOfFrames--;
3096: if (numberOfFrames != 0) {
3097: this .contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
3098: this .contents[numberOfFramesOffset] = (byte) numberOfFrames;
3099:
3100: int attributeLength = localContentsOffset
3101: - stackMapTableAttributeLengthOffset
3102: - 4;
3103: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
3104: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
3105: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
3106: this .contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
3107: attributeNumber++;
3108: } else {
3109: localContentsOffset = stackMapTableAttributeOffset;
3110: }
3111: }
3112: }
3113: }
3114:
3115: if ((this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
3116: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
3117: stackMapFrameCodeStream.removeFramePosition(code_length);
3118: if (stackMapFrameCodeStream.hasFramePositions()) {
3119: ArrayList frames = new ArrayList();
3120: traverse(this .codeStream.methodDeclaration.binding,
3121: max_locals, this .contents,
3122: codeAttributeOffset + 14, code_length, frames,
3123: false);
3124: int numberOfFrames = frames.size();
3125: if (numberOfFrames > 1) {
3126: int stackMapTableAttributeOffset = localContentsOffset;
3127: // add the stack map table attribute
3128: if (localContentsOffset + 8 >= this .contents.length) {
3129: resizeContents(8);
3130: }
3131: int stackMapAttributeNameIndex = constantPool
3132: .literalIndex(AttributeNamesConstants.StackMapName);
3133: this .contents[localContentsOffset++] = (byte) (stackMapAttributeNameIndex >> 8);
3134: this .contents[localContentsOffset++] = (byte) stackMapAttributeNameIndex;
3135:
3136: int stackMapAttributeLengthOffset = localContentsOffset;
3137: // generate the attribute
3138: localContentsOffset += 4;
3139: if (localContentsOffset + 4 >= this .contents.length) {
3140: resizeContents(4);
3141: }
3142: int numberOfFramesOffset = localContentsOffset;
3143: localContentsOffset += 2;
3144: if (localContentsOffset + 2 >= this .contents.length) {
3145: resizeContents(2);
3146: }
3147: StackMapFrame currentFrame = (StackMapFrame) frames
3148: .get(0);
3149: for (int j = 1; j < numberOfFrames; j++) {
3150: // select next frame
3151: currentFrame = (StackMapFrame) frames.get(j);
3152: // generate current frame
3153: // need to find differences between the current frame and the previous frame
3154: int frameOffset = currentFrame.pc;
3155: // FULL_FRAME
3156: if (localContentsOffset + 5 >= this .contents.length) {
3157: resizeContents(5);
3158: }
3159: this .contents[localContentsOffset++] = (byte) (frameOffset >> 8);
3160: this .contents[localContentsOffset++] = (byte) frameOffset;
3161: int numberOfLocalOffset = localContentsOffset;
3162: localContentsOffset += 2; // leave two spots for number of locals
3163: int numberOfLocalEntries = 0;
3164: int numberOfLocals = currentFrame
3165: .getNumberOfLocals();
3166: int numberOfEntries = 0;
3167: int localsLength = currentFrame.locals == null ? 0
3168: : currentFrame.locals.length;
3169: for (int i = 0; i < localsLength
3170: && numberOfLocalEntries < numberOfLocals; i++) {
3171: if (localContentsOffset + 3 >= this .contents.length) {
3172: resizeContents(3);
3173: }
3174: VerificationTypeInfo info = currentFrame.locals[i];
3175: if (info == null) {
3176: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3177: } else {
3178: switch (info.id()) {
3179: case T_boolean:
3180: case T_byte:
3181: case T_char:
3182: case T_int:
3183: case T_short:
3184: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3185: break;
3186: case T_float:
3187: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3188: break;
3189: case T_long:
3190: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3191: i++;
3192: break;
3193: case T_double:
3194: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3195: i++;
3196: break;
3197: case T_null:
3198: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3199: break;
3200: default:
3201: this .contents[localContentsOffset++] = (byte) info.tag;
3202: switch (info.tag) {
3203: case VerificationTypeInfo.ITEM_UNINITIALIZED:
3204: int offset = info.offset;
3205: this .contents[localContentsOffset++] = (byte) (offset >> 8);
3206: this .contents[localContentsOffset++] = (byte) offset;
3207: break;
3208: case VerificationTypeInfo.ITEM_OBJECT:
3209: int indexForType = constantPool
3210: .literalIndexForType(info
3211: .constantPoolName());
3212: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
3213: this .contents[localContentsOffset++] = (byte) indexForType;
3214: }
3215: }
3216: numberOfLocalEntries++;
3217: }
3218: numberOfEntries++;
3219: }
3220: if (localContentsOffset + 4 >= this .contents.length) {
3221: resizeContents(4);
3222: }
3223: this .contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
3224: this .contents[numberOfLocalOffset] = (byte) numberOfEntries;
3225: int numberOfStackItems = currentFrame.numberOfStackItems;
3226: this .contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
3227: this .contents[localContentsOffset++] = (byte) numberOfStackItems;
3228: for (int i = 0; i < numberOfStackItems; i++) {
3229: if (localContentsOffset + 3 >= this .contents.length) {
3230: resizeContents(3);
3231: }
3232: VerificationTypeInfo info = currentFrame.stackItems[i];
3233: if (info == null) {
3234: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3235: } else {
3236: switch (info.id()) {
3237: case T_boolean:
3238: case T_byte:
3239: case T_char:
3240: case T_int:
3241: case T_short:
3242: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3243: break;
3244: case T_float:
3245: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3246: break;
3247: case T_long:
3248: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3249: break;
3250: case T_double:
3251: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3252: break;
3253: case T_null:
3254: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3255: break;
3256: default:
3257: this .contents[localContentsOffset++] = (byte) info.tag;
3258: switch (info.tag) {
3259: case VerificationTypeInfo.ITEM_UNINITIALIZED:
3260: int offset = info.offset;
3261: this .contents[localContentsOffset++] = (byte) (offset >> 8);
3262: this .contents[localContentsOffset++] = (byte) offset;
3263: break;
3264: case VerificationTypeInfo.ITEM_OBJECT:
3265: int indexForType = constantPool
3266: .literalIndexForType(info
3267: .constantPoolName());
3268: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
3269: this .contents[localContentsOffset++] = (byte) indexForType;
3270: }
3271: }
3272: }
3273: }
3274: }
3275:
3276: numberOfFrames--;
3277: if (numberOfFrames != 0) {
3278: this .contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
3279: this .contents[numberOfFramesOffset] = (byte) numberOfFrames;
3280:
3281: int attributeLength = localContentsOffset
3282: - stackMapAttributeLengthOffset - 4;
3283: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 24);
3284: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 16);
3285: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 8);
3286: this .contents[stackMapAttributeLengthOffset] = (byte) attributeLength;
3287: attributeNumber++;
3288: } else {
3289: localContentsOffset = stackMapTableAttributeOffset;
3290: }
3291: }
3292: }
3293: }
3294:
3295: // update the number of attributes
3296: // ensure first that there is enough space available inside the contents array
3297: if (codeAttributeAttributeOffset + 2 >= this .contents.length) {
3298: resizeContents(2);
3299: }
3300: this .contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
3301: this .contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
3302: // update the attribute length
3303: int codeAttributeLength = localContentsOffset
3304: - (codeAttributeOffset + 6);
3305: this .contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
3306: this .contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
3307: this .contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
3308: this .contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
3309: contentsOffset = localContentsOffset;
3310: }
3311:
3312: /**
3313: * INTERNAL USE-ONLY
3314: * That method completes the creation of the code attribute by setting
3315: * - the attribute_length
3316: * - max_stack
3317: * - max_locals
3318: * - code_length
3319: * - exception table
3320: * - and debug attributes if necessary.
3321: */
3322: public void completeCodeAttributeForClinit(int codeAttributeOffset,
3323: int problemLine) {
3324: // reinitialize the contents with the byte modified by the code stream
3325: this .contents = codeStream.bCodeStream;
3326: int localContentsOffset = codeStream.classFileOffset;
3327: // codeAttributeOffset is the position inside contents byte array before we started to write
3328: // any information about the codeAttribute
3329: // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
3330: // to get the right position, 6 for the max_stack etc...
3331: int code_length = codeStream.position;
3332: if (code_length > 65535) {
3333: codeStream.methodDeclaration.scope.problemReporter()
3334: .bytecodeExceeds64KLimit(
3335: codeStream.methodDeclaration.scope
3336: .referenceType());
3337: }
3338: if (localContentsOffset + 20 >= this .contents.length) {
3339: resizeContents(20);
3340: }
3341: int max_stack = codeStream.stackMax;
3342: this .contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
3343: this .contents[codeAttributeOffset + 7] = (byte) max_stack;
3344: int max_locals = codeStream.maxLocals;
3345: this .contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
3346: this .contents[codeAttributeOffset + 9] = (byte) max_locals;
3347: this .contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
3348: this .contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
3349: this .contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
3350: this .contents[codeAttributeOffset + 13] = (byte) code_length;
3351:
3352: // write the exception table
3353: this .contents[localContentsOffset++] = 0;
3354: this .contents[localContentsOffset++] = 0;
3355:
3356: // debug attributes
3357: int codeAttributeAttributeOffset = localContentsOffset;
3358: int attributeNumber = 0; // leave two bytes for the attribute_length
3359: localContentsOffset += 2; // first we handle the linenumber attribute
3360: if (localContentsOffset + 2 >= this .contents.length) {
3361: resizeContents(2);
3362: }
3363:
3364: // first we handle the linenumber attribute
3365: if ((this .produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
3366: if (localContentsOffset + 20 >= this .contents.length) {
3367: resizeContents(20);
3368: }
3369: /* Create and add the line number attribute (used for debugging)
3370: * Build the pairs of:
3371: * (bytecodePC lineNumber)
3372: * according to the table of start line indexes and the pcToSourceMap table
3373: * contained into the codestream
3374: */
3375: int lineNumberNameIndex = constantPool
3376: .literalIndex(AttributeNamesConstants.LineNumberTableName);
3377: this .contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
3378: this .contents[localContentsOffset++] = (byte) lineNumberNameIndex;
3379: this .contents[localContentsOffset++] = 0;
3380: this .contents[localContentsOffset++] = 0;
3381: this .contents[localContentsOffset++] = 0;
3382: this .contents[localContentsOffset++] = 6;
3383: this .contents[localContentsOffset++] = 0;
3384: this .contents[localContentsOffset++] = 1;
3385: // first entry at pc = 0
3386: this .contents[localContentsOffset++] = 0;
3387: this .contents[localContentsOffset++] = 0;
3388: this .contents[localContentsOffset++] = (byte) (problemLine >> 8);
3389: this .contents[localContentsOffset++] = (byte) problemLine;
3390: // now we change the size of the line number attribute
3391: attributeNumber++;
3392: }
3393: // then we do the local variable attribute
3394: if ((this .produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
3395: int localVariableNameIndex = constantPool
3396: .literalIndex(AttributeNamesConstants.LocalVariableTableName);
3397: if (localContentsOffset + 8 >= this .contents.length) {
3398: resizeContents(8);
3399: }
3400: this .contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
3401: this .contents[localContentsOffset++] = (byte) localVariableNameIndex;
3402: this .contents[localContentsOffset++] = 0;
3403: this .contents[localContentsOffset++] = 0;
3404: this .contents[localContentsOffset++] = 0;
3405: this .contents[localContentsOffset++] = 2;
3406: this .contents[localContentsOffset++] = 0;
3407: this .contents[localContentsOffset++] = 0;
3408: attributeNumber++;
3409: }
3410:
3411: if ((this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) {
3412: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
3413: stackMapFrameCodeStream.removeFramePosition(code_length);
3414: if (stackMapFrameCodeStream.hasFramePositions()) {
3415: ArrayList frames = new ArrayList();
3416: traverse(null, max_locals, this .contents,
3417: codeAttributeOffset + 14, code_length, frames,
3418: true);
3419: int numberOfFrames = frames.size();
3420: if (numberOfFrames > 1) {
3421: int stackMapTableAttributeOffset = localContentsOffset;
3422: // add the stack map table attribute
3423: if (localContentsOffset + 8 >= this .contents.length) {
3424: resizeContents(8);
3425: }
3426: int stackMapTableAttributeNameIndex = constantPool
3427: .literalIndex(AttributeNamesConstants.StackMapTableName);
3428: this .contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
3429: this .contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
3430:
3431: int stackMapTableAttributeLengthOffset = localContentsOffset;
3432: // generate the attribute
3433: localContentsOffset += 4;
3434: if (localContentsOffset + 4 >= this .contents.length) {
3435: resizeContents(4);
3436: }
3437: numberOfFrames = 0;
3438: int numberOfFramesOffset = localContentsOffset;
3439: localContentsOffset += 2;
3440: if (localContentsOffset + 2 >= this .contents.length) {
3441: resizeContents(2);
3442: }
3443: StackMapFrame currentFrame = (StackMapFrame) frames
3444: .get(0);
3445: StackMapFrame prevFrame = null;
3446: for (int j = 1; j < numberOfFrames; j++) {
3447: // select next frame
3448: prevFrame = currentFrame;
3449: currentFrame = (StackMapFrame) frames.get(j);
3450: // generate current frame
3451: // need to find differences between the current frame and the previous frame
3452: numberOfFrames++;
3453: int offsetDelta = currentFrame
3454: .getOffsetDelta(prevFrame);
3455: switch (currentFrame.getFrameType(prevFrame)) {
3456: case StackMapFrame.APPEND_FRAME:
3457: if (localContentsOffset + 3 >= this .contents.length) {
3458: resizeContents(3);
3459: }
3460: int numberOfDifferentLocals = currentFrame
3461: .numberOfDifferentLocals(prevFrame);
3462: this .contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
3463: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
3464: this .contents[localContentsOffset++] = (byte) offsetDelta;
3465: int index = currentFrame
3466: .getIndexOfDifferentLocals(numberOfDifferentLocals);
3467: int numberOfLocals = currentFrame
3468: .getNumberOfLocals();
3469: for (int i = index; i < currentFrame.locals.length
3470: && numberOfDifferentLocals > 0; i++) {
3471: if (localContentsOffset + 6 >= this .contents.length) {
3472: resizeContents(6);
3473: }
3474: VerificationTypeInfo info = currentFrame.locals[i];
3475: if (info == null) {
3476: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3477: } else {
3478: switch (info.id()) {
3479: case T_boolean:
3480: case T_byte:
3481: case T_char:
3482: case T_int:
3483: case T_short:
3484: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3485: break;
3486: case T_float:
3487: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3488: break;
3489: case T_long:
3490: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3491: i++;
3492: break;
3493: case T_double:
3494: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3495: i++;
3496: break;
3497: case T_null:
3498: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3499: break;
3500: default:
3501: this .contents[localContentsOffset++] = (byte) info.tag;
3502: switch (info.tag) {
3503: case VerificationTypeInfo.ITEM_UNINITIALIZED:
3504: int offset = info.offset;
3505: this .contents[localContentsOffset++] = (byte) (offset >> 8);
3506: this .contents[localContentsOffset++] = (byte) offset;
3507: break;
3508: case VerificationTypeInfo.ITEM_OBJECT:
3509: int indexForType = constantPool
3510: .literalIndexForType(info
3511: .constantPoolName());
3512: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
3513: this .contents[localContentsOffset++] = (byte) indexForType;
3514: }
3515: }
3516: numberOfDifferentLocals--;
3517: }
3518: }
3519: break;
3520: case StackMapFrame.SAME_FRAME:
3521: if (localContentsOffset + 1 >= this .contents.length) {
3522: resizeContents(1);
3523: }
3524: this .contents[localContentsOffset++] = (byte) offsetDelta;
3525: break;
3526: case StackMapFrame.SAME_FRAME_EXTENDED:
3527: if (localContentsOffset + 3 >= this .contents.length) {
3528: resizeContents(3);
3529: }
3530: this .contents[localContentsOffset++] = (byte) 251;
3531: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
3532: this .contents[localContentsOffset++] = (byte) offsetDelta;
3533: break;
3534: case StackMapFrame.CHOP_FRAME:
3535: if (localContentsOffset + 3 >= this .contents.length) {
3536: resizeContents(3);
3537: }
3538: numberOfDifferentLocals = -currentFrame
3539: .numberOfDifferentLocals(prevFrame);
3540: this .contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
3541: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
3542: this .contents[localContentsOffset++] = (byte) offsetDelta;
3543: break;
3544: case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS:
3545: if (localContentsOffset + 4 >= this .contents.length) {
3546: resizeContents(4);
3547: }
3548: this .contents[localContentsOffset++] = (byte) (offsetDelta + 64);
3549: if (currentFrame.stackItems[0] == null) {
3550: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3551: } else {
3552: switch (currentFrame.stackItems[0].id()) {
3553: case T_boolean:
3554: case T_byte:
3555: case T_char:
3556: case T_int:
3557: case T_short:
3558: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3559: break;
3560: case T_float:
3561: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3562: break;
3563: case T_long:
3564: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3565: break;
3566: case T_double:
3567: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3568: break;
3569: case T_null:
3570: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3571: break;
3572: default:
3573: VerificationTypeInfo info = currentFrame.stackItems[0];
3574: byte tag = (byte) info.tag;
3575: this .contents[localContentsOffset++] = tag;
3576: switch (tag) {
3577: case VerificationTypeInfo.ITEM_UNINITIALIZED:
3578: int offset = info.offset;
3579: this .contents[localContentsOffset++] = (byte) (offset >> 8);
3580: this .contents[localContentsOffset++] = (byte) offset;
3581: break;
3582: case VerificationTypeInfo.ITEM_OBJECT:
3583: int indexForType = constantPool
3584: .literalIndexForType(info
3585: .constantPoolName());
3586: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
3587: this .contents[localContentsOffset++] = (byte) indexForType;
3588: }
3589: }
3590: }
3591: break;
3592: case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED:
3593: if (localContentsOffset + 6 >= this .contents.length) {
3594: resizeContents(6);
3595: }
3596: this .contents[localContentsOffset++] = (byte) 247;
3597: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
3598: this .contents[localContentsOffset++] = (byte) offsetDelta;
3599: if (currentFrame.stackItems[0] == null) {
3600: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3601: } else {
3602: switch (currentFrame.stackItems[0].id()) {
3603: case T_boolean:
3604: case T_byte:
3605: case T_char:
3606: case T_int:
3607: case T_short:
3608: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3609: break;
3610: case T_float:
3611: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3612: break;
3613: case T_long:
3614: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3615: break;
3616: case T_double:
3617: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3618: break;
3619: case T_null:
3620: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3621: break;
3622: default:
3623: VerificationTypeInfo info = currentFrame.stackItems[0];
3624: byte tag = (byte) info.tag;
3625: this .contents[localContentsOffset++] = tag;
3626: switch (tag) {
3627: case VerificationTypeInfo.ITEM_UNINITIALIZED:
3628: int offset = info.offset;
3629: this .contents[localContentsOffset++] = (byte) (offset >> 8);
3630: this .contents[localContentsOffset++] = (byte) offset;
3631: break;
3632: case VerificationTypeInfo.ITEM_OBJECT:
3633: int indexForType = constantPool
3634: .literalIndexForType(info
3635: .constantPoolName());
3636: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
3637: this .contents[localContentsOffset++] = (byte) indexForType;
3638: }
3639: }
3640: }
3641: break;
3642: default:
3643: // FULL_FRAME
3644: if (localContentsOffset + 5 >= this .contents.length) {
3645: resizeContents(5);
3646: }
3647: this .contents[localContentsOffset++] = (byte) 255;
3648: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
3649: this .contents[localContentsOffset++] = (byte) offsetDelta;
3650: int numberOfLocalOffset = localContentsOffset;
3651: localContentsOffset += 2; // leave two spots for number of locals
3652: int numberOfLocalEntries = 0;
3653: numberOfLocals = currentFrame
3654: .getNumberOfLocals();
3655: int numberOfEntries = 0;
3656: int localsLength = currentFrame.locals == null ? 0
3657: : currentFrame.locals.length;
3658: for (int i = 0; i < localsLength
3659: && numberOfLocalEntries < numberOfLocals; i++) {
3660: if (localContentsOffset + 3 >= this .contents.length) {
3661: resizeContents(3);
3662: }
3663: VerificationTypeInfo info = currentFrame.locals[i];
3664: if (info == null) {
3665: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3666: } else {
3667: switch (info.id()) {
3668: case T_boolean:
3669: case T_byte:
3670: case T_char:
3671: case T_int:
3672: case T_short:
3673: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3674: break;
3675: case T_float:
3676: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3677: break;
3678: case T_long:
3679: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3680: i++;
3681: break;
3682: case T_double:
3683: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3684: i++;
3685: break;
3686: case T_null:
3687: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3688: break;
3689: default:
3690: this .contents[localContentsOffset++] = (byte) info.tag;
3691: switch (info.tag) {
3692: case VerificationTypeInfo.ITEM_UNINITIALIZED:
3693: int offset = info.offset;
3694: this .contents[localContentsOffset++] = (byte) (offset >> 8);
3695: this .contents[localContentsOffset++] = (byte) offset;
3696: break;
3697: case VerificationTypeInfo.ITEM_OBJECT:
3698: int indexForType = constantPool
3699: .literalIndexForType(info
3700: .constantPoolName());
3701: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
3702: this .contents[localContentsOffset++] = (byte) indexForType;
3703: }
3704: }
3705: numberOfLocalEntries++;
3706: }
3707: numberOfEntries++;
3708: }
3709: if (localContentsOffset + 4 >= this .contents.length) {
3710: resizeContents(4);
3711: }
3712: this .contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
3713: this .contents[numberOfLocalOffset] = (byte) numberOfEntries;
3714: int numberOfStackItems = currentFrame.numberOfStackItems;
3715: this .contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
3716: this .contents[localContentsOffset++] = (byte) numberOfStackItems;
3717: for (int i = 0; i < numberOfStackItems; i++) {
3718: if (localContentsOffset + 3 >= this .contents.length) {
3719: resizeContents(3);
3720: }
3721: VerificationTypeInfo info = currentFrame.stackItems[i];
3722: if (info == null) {
3723: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3724: } else {
3725: switch (info.id()) {
3726: case T_boolean:
3727: case T_byte:
3728: case T_char:
3729: case T_int:
3730: case T_short:
3731: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3732: break;
3733: case T_float:
3734: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3735: break;
3736: case T_long:
3737: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3738: break;
3739: case T_double:
3740: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3741: break;
3742: case T_null:
3743: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3744: break;
3745: default:
3746: this .contents[localContentsOffset++] = (byte) info.tag;
3747: switch (info.tag) {
3748: case VerificationTypeInfo.ITEM_UNINITIALIZED:
3749: int offset = info.offset;
3750: this .contents[localContentsOffset++] = (byte) (offset >> 8);
3751: this .contents[localContentsOffset++] = (byte) offset;
3752: break;
3753: case VerificationTypeInfo.ITEM_OBJECT:
3754: int indexForType = constantPool
3755: .literalIndexForType(info
3756: .constantPoolName());
3757: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
3758: this .contents[localContentsOffset++] = (byte) indexForType;
3759: }
3760: }
3761: }
3762: }
3763: }
3764: }
3765:
3766: if (numberOfFrames != 0) {
3767: this .contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
3768: this .contents[numberOfFramesOffset] = (byte) numberOfFrames;
3769:
3770: int attributeLength = localContentsOffset
3771: - stackMapTableAttributeLengthOffset
3772: - 4;
3773: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
3774: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
3775: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
3776: this .contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
3777: attributeNumber++;
3778: } else {
3779: localContentsOffset = stackMapTableAttributeOffset;
3780: }
3781: }
3782: }
3783: }
3784:
3785: if ((this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
3786: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
3787: stackMapFrameCodeStream.removeFramePosition(code_length);
3788: if (stackMapFrameCodeStream.hasFramePositions()) {
3789: ArrayList frames = new ArrayList();
3790: traverse(this .codeStream.methodDeclaration.binding,
3791: max_locals, this .contents,
3792: codeAttributeOffset + 14, code_length, frames,
3793: false);
3794: int numberOfFrames = frames.size();
3795: if (numberOfFrames > 1) {
3796: int stackMapTableAttributeOffset = localContentsOffset;
3797: // add the stack map table attribute
3798: if (localContentsOffset + 8 >= this .contents.length) {
3799: resizeContents(8);
3800: }
3801: int stackMapAttributeNameIndex = constantPool
3802: .literalIndex(AttributeNamesConstants.StackMapName);
3803: this .contents[localContentsOffset++] = (byte) (stackMapAttributeNameIndex >> 8);
3804: this .contents[localContentsOffset++] = (byte) stackMapAttributeNameIndex;
3805:
3806: int stackMapAttributeLengthOffset = localContentsOffset;
3807: // generate the attribute
3808: localContentsOffset += 4;
3809: if (localContentsOffset + 4 >= this .contents.length) {
3810: resizeContents(4);
3811: }
3812: int numberOfFramesOffset = localContentsOffset;
3813: localContentsOffset += 2;
3814: if (localContentsOffset + 2 >= this .contents.length) {
3815: resizeContents(2);
3816: }
3817: StackMapFrame currentFrame = (StackMapFrame) frames
3818: .get(0);
3819: for (int j = 1; j < numberOfFrames; j++) {
3820: // select next frame
3821: currentFrame = (StackMapFrame) frames.get(j);
3822: // generate current frame
3823: // need to find differences between the current frame and the previous frame
3824: int frameOffset = currentFrame.pc;
3825: // FULL_FRAME
3826: if (localContentsOffset + 5 >= this .contents.length) {
3827: resizeContents(5);
3828: }
3829: this .contents[localContentsOffset++] = (byte) (frameOffset >> 8);
3830: this .contents[localContentsOffset++] = (byte) frameOffset;
3831: int numberOfLocalOffset = localContentsOffset;
3832: localContentsOffset += 2; // leave two spots for number of locals
3833: int numberOfLocalEntries = 0;
3834: int numberOfLocals = currentFrame
3835: .getNumberOfLocals();
3836: int numberOfEntries = 0;
3837: int localsLength = currentFrame.locals == null ? 0
3838: : currentFrame.locals.length;
3839: for (int i = 0; i < localsLength
3840: && numberOfLocalEntries < numberOfLocals; i++) {
3841: if (localContentsOffset + 3 >= this .contents.length) {
3842: resizeContents(3);
3843: }
3844: VerificationTypeInfo info = currentFrame.locals[i];
3845: if (info == null) {
3846: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3847: } else {
3848: switch (info.id()) {
3849: case T_boolean:
3850: case T_byte:
3851: case T_char:
3852: case T_int:
3853: case T_short:
3854: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3855: break;
3856: case T_float:
3857: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3858: break;
3859: case T_long:
3860: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3861: i++;
3862: break;
3863: case T_double:
3864: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3865: i++;
3866: break;
3867: case T_null:
3868: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3869: break;
3870: default:
3871: this .contents[localContentsOffset++] = (byte) info.tag;
3872: switch (info.tag) {
3873: case VerificationTypeInfo.ITEM_UNINITIALIZED:
3874: int offset = info.offset;
3875: this .contents[localContentsOffset++] = (byte) (offset >> 8);
3876: this .contents[localContentsOffset++] = (byte) offset;
3877: break;
3878: case VerificationTypeInfo.ITEM_OBJECT:
3879: int indexForType = constantPool
3880: .literalIndexForType(info
3881: .constantPoolName());
3882: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
3883: this .contents[localContentsOffset++] = (byte) indexForType;
3884: }
3885: }
3886: numberOfLocalEntries++;
3887: }
3888: numberOfEntries++;
3889: }
3890: if (localContentsOffset + 4 >= this .contents.length) {
3891: resizeContents(4);
3892: }
3893: this .contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
3894: this .contents[numberOfLocalOffset] = (byte) numberOfEntries;
3895: int numberOfStackItems = currentFrame.numberOfStackItems;
3896: this .contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
3897: this .contents[localContentsOffset++] = (byte) numberOfStackItems;
3898: for (int i = 0; i < numberOfStackItems; i++) {
3899: if (localContentsOffset + 3 >= this .contents.length) {
3900: resizeContents(3);
3901: }
3902: VerificationTypeInfo info = currentFrame.stackItems[i];
3903: if (info == null) {
3904: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
3905: } else {
3906: switch (info.id()) {
3907: case T_boolean:
3908: case T_byte:
3909: case T_char:
3910: case T_int:
3911: case T_short:
3912: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
3913: break;
3914: case T_float:
3915: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
3916: break;
3917: case T_long:
3918: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
3919: break;
3920: case T_double:
3921: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
3922: break;
3923: case T_null:
3924: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
3925: break;
3926: default:
3927: this .contents[localContentsOffset++] = (byte) info.tag;
3928: switch (info.tag) {
3929: case VerificationTypeInfo.ITEM_UNINITIALIZED:
3930: int offset = info.offset;
3931: this .contents[localContentsOffset++] = (byte) (offset >> 8);
3932: this .contents[localContentsOffset++] = (byte) offset;
3933: break;
3934: case VerificationTypeInfo.ITEM_OBJECT:
3935: int indexForType = constantPool
3936: .literalIndexForType(info
3937: .constantPoolName());
3938: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
3939: this .contents[localContentsOffset++] = (byte) indexForType;
3940: }
3941: }
3942: }
3943: }
3944: }
3945:
3946: numberOfFrames--;
3947: if (numberOfFrames != 0) {
3948: this .contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
3949: this .contents[numberOfFramesOffset] = (byte) numberOfFrames;
3950:
3951: int attributeLength = localContentsOffset
3952: - stackMapAttributeLengthOffset - 4;
3953: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 24);
3954: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 16);
3955: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 8);
3956: this .contents[stackMapAttributeLengthOffset] = (byte) attributeLength;
3957: attributeNumber++;
3958: } else {
3959: localContentsOffset = stackMapTableAttributeOffset;
3960: }
3961: }
3962: }
3963: }
3964:
3965: // update the number of attributes
3966: // ensure first that there is enough space available inside the contents array
3967: if (codeAttributeAttributeOffset + 2 >= this .contents.length) {
3968: resizeContents(2);
3969: }
3970: this .contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
3971: this .contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
3972: // update the attribute length
3973: int codeAttributeLength = localContentsOffset
3974: - (codeAttributeOffset + 6);
3975: this .contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
3976: this .contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
3977: this .contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
3978: this .contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
3979: contentsOffset = localContentsOffset;
3980: }
3981:
3982: /**
3983: *
3984: */
3985: public void completeCodeAttributeForMissingAbstractProblemMethod(
3986: MethodBinding binding, int codeAttributeOffset,
3987: int[] startLineIndexes, int problemLine) {
3988: // reinitialize the localContents with the byte modified by the code stream
3989: this .contents = codeStream.bCodeStream;
3990: int localContentsOffset = codeStream.classFileOffset;
3991: // 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...
3992: int max_stack = codeStream.stackMax;
3993: this .contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
3994: this .contents[codeAttributeOffset + 7] = (byte) max_stack;
3995: int max_locals = codeStream.maxLocals;
3996: this .contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
3997: this .contents[codeAttributeOffset + 9] = (byte) max_locals;
3998: int code_length = codeStream.position;
3999: this .contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
4000: this .contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
4001: this .contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
4002: this .contents[codeAttributeOffset + 13] = (byte) code_length;
4003: // write the exception table
4004: if (localContentsOffset + 50 >= this .contents.length) {
4005: resizeContents(50);
4006: }
4007: this .contents[localContentsOffset++] = 0;
4008: this .contents[localContentsOffset++] = 0;
4009: // debug attributes
4010: int codeAttributeAttributeOffset = localContentsOffset;
4011: int attributeNumber = 0; // leave two bytes for the attribute_length
4012: localContentsOffset += 2; // first we handle the linenumber attribute
4013: if (localContentsOffset + 2 >= this .contents.length) {
4014: resizeContents(2);
4015: }
4016:
4017: if ((this .produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
4018: if (localContentsOffset + 12 >= this .contents.length) {
4019: resizeContents(12);
4020: }
4021: /* Create and add the line number attribute (used for debugging)
4022: * Build the pairs of:
4023: * (bytecodePC lineNumber)
4024: * according to the table of start line indexes and the pcToSourceMap table
4025: * contained into the codestream
4026: */
4027: int lineNumberNameIndex = constantPool
4028: .literalIndex(AttributeNamesConstants.LineNumberTableName);
4029: this .contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
4030: this .contents[localContentsOffset++] = (byte) lineNumberNameIndex;
4031: this .contents[localContentsOffset++] = 0;
4032: this .contents[localContentsOffset++] = 0;
4033: this .contents[localContentsOffset++] = 0;
4034: this .contents[localContentsOffset++] = 6;
4035: this .contents[localContentsOffset++] = 0;
4036: this .contents[localContentsOffset++] = 1;
4037: if (problemLine == 0) {
4038: problemLine = Util.getLineNumber(binding.sourceStart(),
4039: startLineIndexes, 0,
4040: startLineIndexes.length - 1);
4041: }
4042: // first entry at pc = 0
4043: this .contents[localContentsOffset++] = 0;
4044: this .contents[localContentsOffset++] = 0;
4045: this .contents[localContentsOffset++] = (byte) (problemLine >> 8);
4046: this .contents[localContentsOffset++] = (byte) problemLine;
4047: // now we change the size of the line number attribute
4048: attributeNumber++;
4049: }
4050:
4051: if ((this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) {
4052: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
4053: stackMapFrameCodeStream.removeFramePosition(code_length);
4054: if (stackMapFrameCodeStream.hasFramePositions()) {
4055: ArrayList frames = new ArrayList();
4056: traverse(binding, max_locals, this .contents,
4057: codeAttributeOffset + 14, code_length, frames,
4058: false);
4059: int numberOfFrames = frames.size();
4060: if (numberOfFrames > 1) {
4061: int stackMapTableAttributeOffset = localContentsOffset;
4062: // add the stack map table attribute
4063: if (localContentsOffset + 8 >= this .contents.length) {
4064: resizeContents(8);
4065: }
4066: int stackMapTableAttributeNameIndex = constantPool
4067: .literalIndex(AttributeNamesConstants.StackMapTableName);
4068: this .contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
4069: this .contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
4070:
4071: int stackMapTableAttributeLengthOffset = localContentsOffset;
4072: // generate the attribute
4073: localContentsOffset += 4;
4074: if (localContentsOffset + 4 >= this .contents.length) {
4075: resizeContents(4);
4076: }
4077: numberOfFrames = 0;
4078: int numberOfFramesOffset = localContentsOffset;
4079: localContentsOffset += 2;
4080: if (localContentsOffset + 2 >= this .contents.length) {
4081: resizeContents(2);
4082: }
4083: StackMapFrame currentFrame = (StackMapFrame) frames
4084: .get(0);
4085: StackMapFrame prevFrame = null;
4086: for (int j = 1; j < numberOfFrames; j++) {
4087: // select next frame
4088: prevFrame = currentFrame;
4089: currentFrame = (StackMapFrame) frames.get(j);
4090: // generate current frame
4091: // need to find differences between the current frame and the previous frame
4092: numberOfFrames++;
4093: int offsetDelta = currentFrame
4094: .getOffsetDelta(prevFrame);
4095: switch (currentFrame.getFrameType(prevFrame)) {
4096: case StackMapFrame.APPEND_FRAME:
4097: if (localContentsOffset + 3 >= this .contents.length) {
4098: resizeContents(3);
4099: }
4100: int numberOfDifferentLocals = currentFrame
4101: .numberOfDifferentLocals(prevFrame);
4102: this .contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
4103: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4104: this .contents[localContentsOffset++] = (byte) offsetDelta;
4105: int index = currentFrame
4106: .getIndexOfDifferentLocals(numberOfDifferentLocals);
4107: int numberOfLocals = currentFrame
4108: .getNumberOfLocals();
4109: for (int i = index; i < currentFrame.locals.length
4110: && numberOfDifferentLocals > 0; i++) {
4111: if (localContentsOffset + 6 >= this .contents.length) {
4112: resizeContents(6);
4113: }
4114: VerificationTypeInfo info = currentFrame.locals[i];
4115: if (info == null) {
4116: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4117: } else {
4118: switch (info.id()) {
4119: case T_boolean:
4120: case T_byte:
4121: case T_char:
4122: case T_int:
4123: case T_short:
4124: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4125: break;
4126: case T_float:
4127: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4128: break;
4129: case T_long:
4130: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4131: i++;
4132: break;
4133: case T_double:
4134: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4135: i++;
4136: break;
4137: case T_null:
4138: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4139: break;
4140: default:
4141: this .contents[localContentsOffset++] = (byte) info.tag;
4142: switch (info.tag) {
4143: case VerificationTypeInfo.ITEM_UNINITIALIZED:
4144: int offset = info.offset;
4145: this .contents[localContentsOffset++] = (byte) (offset >> 8);
4146: this .contents[localContentsOffset++] = (byte) offset;
4147: break;
4148: case VerificationTypeInfo.ITEM_OBJECT:
4149: int indexForType = constantPool
4150: .literalIndexForType(info
4151: .constantPoolName());
4152: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
4153: this .contents[localContentsOffset++] = (byte) indexForType;
4154: }
4155: }
4156: numberOfDifferentLocals--;
4157: }
4158: }
4159: break;
4160: case StackMapFrame.SAME_FRAME:
4161: if (localContentsOffset + 1 >= this .contents.length) {
4162: resizeContents(1);
4163: }
4164: this .contents[localContentsOffset++] = (byte) offsetDelta;
4165: break;
4166: case StackMapFrame.SAME_FRAME_EXTENDED:
4167: if (localContentsOffset + 3 >= this .contents.length) {
4168: resizeContents(3);
4169: }
4170: this .contents[localContentsOffset++] = (byte) 251;
4171: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4172: this .contents[localContentsOffset++] = (byte) offsetDelta;
4173: break;
4174: case StackMapFrame.CHOP_FRAME:
4175: if (localContentsOffset + 3 >= this .contents.length) {
4176: resizeContents(3);
4177: }
4178: numberOfDifferentLocals = -currentFrame
4179: .numberOfDifferentLocals(prevFrame);
4180: this .contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
4181: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4182: this .contents[localContentsOffset++] = (byte) offsetDelta;
4183: break;
4184: case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS:
4185: if (localContentsOffset + 4 >= this .contents.length) {
4186: resizeContents(4);
4187: }
4188: this .contents[localContentsOffset++] = (byte) (offsetDelta + 64);
4189: if (currentFrame.stackItems[0] == null) {
4190: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4191: } else {
4192: switch (currentFrame.stackItems[0].id()) {
4193: case T_boolean:
4194: case T_byte:
4195: case T_char:
4196: case T_int:
4197: case T_short:
4198: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4199: break;
4200: case T_float:
4201: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4202: break;
4203: case T_long:
4204: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4205: break;
4206: case T_double:
4207: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4208: break;
4209: case T_null:
4210: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4211: break;
4212: default:
4213: VerificationTypeInfo info = currentFrame.stackItems[0];
4214: byte tag = (byte) info.tag;
4215: this .contents[localContentsOffset++] = tag;
4216: switch (tag) {
4217: case VerificationTypeInfo.ITEM_UNINITIALIZED:
4218: int offset = info.offset;
4219: this .contents[localContentsOffset++] = (byte) (offset >> 8);
4220: this .contents[localContentsOffset++] = (byte) offset;
4221: break;
4222: case VerificationTypeInfo.ITEM_OBJECT:
4223: int indexForType = constantPool
4224: .literalIndexForType(info
4225: .constantPoolName());
4226: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
4227: this .contents[localContentsOffset++] = (byte) indexForType;
4228: }
4229: }
4230: }
4231: break;
4232: case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED:
4233: if (localContentsOffset + 6 >= this .contents.length) {
4234: resizeContents(6);
4235: }
4236: this .contents[localContentsOffset++] = (byte) 247;
4237: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4238: this .contents[localContentsOffset++] = (byte) offsetDelta;
4239: if (currentFrame.stackItems[0] == null) {
4240: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4241: } else {
4242: switch (currentFrame.stackItems[0].id()) {
4243: case T_boolean:
4244: case T_byte:
4245: case T_char:
4246: case T_int:
4247: case T_short:
4248: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4249: break;
4250: case T_float:
4251: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4252: break;
4253: case T_long:
4254: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4255: break;
4256: case T_double:
4257: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4258: break;
4259: case T_null:
4260: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4261: break;
4262: default:
4263: VerificationTypeInfo info = currentFrame.stackItems[0];
4264: byte tag = (byte) info.tag;
4265: this .contents[localContentsOffset++] = tag;
4266: switch (tag) {
4267: case VerificationTypeInfo.ITEM_UNINITIALIZED:
4268: int offset = info.offset;
4269: this .contents[localContentsOffset++] = (byte) (offset >> 8);
4270: this .contents[localContentsOffset++] = (byte) offset;
4271: break;
4272: case VerificationTypeInfo.ITEM_OBJECT:
4273: int indexForType = constantPool
4274: .literalIndexForType(info
4275: .constantPoolName());
4276: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
4277: this .contents[localContentsOffset++] = (byte) indexForType;
4278: }
4279: }
4280: }
4281: break;
4282: default:
4283: // FULL_FRAME
4284: if (localContentsOffset + 5 >= this .contents.length) {
4285: resizeContents(5);
4286: }
4287: this .contents[localContentsOffset++] = (byte) 255;
4288: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
4289: this .contents[localContentsOffset++] = (byte) offsetDelta;
4290: int numberOfLocalOffset = localContentsOffset;
4291: localContentsOffset += 2; // leave two spots for number of locals
4292: int numberOfLocalEntries = 0;
4293: numberOfLocals = currentFrame
4294: .getNumberOfLocals();
4295: int numberOfEntries = 0;
4296: int localsLength = currentFrame.locals == null ? 0
4297: : currentFrame.locals.length;
4298: for (int i = 0; i < localsLength
4299: && numberOfLocalEntries < numberOfLocals; i++) {
4300: if (localContentsOffset + 3 >= this .contents.length) {
4301: resizeContents(3);
4302: }
4303: VerificationTypeInfo info = currentFrame.locals[i];
4304: if (info == null) {
4305: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4306: } else {
4307: switch (info.id()) {
4308: case T_boolean:
4309: case T_byte:
4310: case T_char:
4311: case T_int:
4312: case T_short:
4313: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4314: break;
4315: case T_float:
4316: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4317: break;
4318: case T_long:
4319: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4320: i++;
4321: break;
4322: case T_double:
4323: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4324: i++;
4325: break;
4326: case T_null:
4327: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4328: break;
4329: default:
4330: this .contents[localContentsOffset++] = (byte) info.tag;
4331: switch (info.tag) {
4332: case VerificationTypeInfo.ITEM_UNINITIALIZED:
4333: int offset = info.offset;
4334: this .contents[localContentsOffset++] = (byte) (offset >> 8);
4335: this .contents[localContentsOffset++] = (byte) offset;
4336: break;
4337: case VerificationTypeInfo.ITEM_OBJECT:
4338: int indexForType = constantPool
4339: .literalIndexForType(info
4340: .constantPoolName());
4341: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
4342: this .contents[localContentsOffset++] = (byte) indexForType;
4343: }
4344: }
4345: numberOfLocalEntries++;
4346: }
4347: numberOfEntries++;
4348: }
4349: if (localContentsOffset + 4 >= this .contents.length) {
4350: resizeContents(4);
4351: }
4352: this .contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
4353: this .contents[numberOfLocalOffset] = (byte) numberOfEntries;
4354: int numberOfStackItems = currentFrame.numberOfStackItems;
4355: this .contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
4356: this .contents[localContentsOffset++] = (byte) numberOfStackItems;
4357: for (int i = 0; i < numberOfStackItems; i++) {
4358: if (localContentsOffset + 3 >= this .contents.length) {
4359: resizeContents(3);
4360: }
4361: VerificationTypeInfo info = currentFrame.stackItems[i];
4362: if (info == null) {
4363: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4364: } else {
4365: switch (info.id()) {
4366: case T_boolean:
4367: case T_byte:
4368: case T_char:
4369: case T_int:
4370: case T_short:
4371: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4372: break;
4373: case T_float:
4374: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4375: break;
4376: case T_long:
4377: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4378: break;
4379: case T_double:
4380: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4381: break;
4382: case T_null:
4383: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4384: break;
4385: default:
4386: this .contents[localContentsOffset++] = (byte) info.tag;
4387: switch (info.tag) {
4388: case VerificationTypeInfo.ITEM_UNINITIALIZED:
4389: int offset = info.offset;
4390: this .contents[localContentsOffset++] = (byte) (offset >> 8);
4391: this .contents[localContentsOffset++] = (byte) offset;
4392: break;
4393: case VerificationTypeInfo.ITEM_OBJECT:
4394: int indexForType = constantPool
4395: .literalIndexForType(info
4396: .constantPoolName());
4397: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
4398: this .contents[localContentsOffset++] = (byte) indexForType;
4399: }
4400: }
4401: }
4402: }
4403: }
4404: }
4405:
4406: if (numberOfFrames != 0) {
4407: this .contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
4408: this .contents[numberOfFramesOffset] = (byte) numberOfFrames;
4409:
4410: int attributeLength = localContentsOffset
4411: - stackMapTableAttributeLengthOffset
4412: - 4;
4413: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
4414: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
4415: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
4416: this .contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
4417: attributeNumber++;
4418: } else {
4419: localContentsOffset = stackMapTableAttributeOffset;
4420: }
4421: }
4422: }
4423: }
4424:
4425: if ((this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
4426: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
4427: stackMapFrameCodeStream.removeFramePosition(code_length);
4428: if (stackMapFrameCodeStream.hasFramePositions()) {
4429: ArrayList frames = new ArrayList();
4430: traverse(this .codeStream.methodDeclaration.binding,
4431: max_locals, this .contents,
4432: codeAttributeOffset + 14, code_length, frames,
4433: false);
4434: int numberOfFrames = frames.size();
4435: if (numberOfFrames > 1) {
4436: int stackMapTableAttributeOffset = localContentsOffset;
4437: // add the stack map table attribute
4438: if (localContentsOffset + 8 >= this .contents.length) {
4439: resizeContents(8);
4440: }
4441: int stackMapAttributeNameIndex = constantPool
4442: .literalIndex(AttributeNamesConstants.StackMapName);
4443: this .contents[localContentsOffset++] = (byte) (stackMapAttributeNameIndex >> 8);
4444: this .contents[localContentsOffset++] = (byte) stackMapAttributeNameIndex;
4445:
4446: int stackMapAttributeLengthOffset = localContentsOffset;
4447: // generate the attribute
4448: localContentsOffset += 4;
4449: if (localContentsOffset + 4 >= this .contents.length) {
4450: resizeContents(4);
4451: }
4452: int numberOfFramesOffset = localContentsOffset;
4453: localContentsOffset += 2;
4454: if (localContentsOffset + 2 >= this .contents.length) {
4455: resizeContents(2);
4456: }
4457: StackMapFrame currentFrame = (StackMapFrame) frames
4458: .get(0);
4459: for (int j = 1; j < numberOfFrames; j++) {
4460: // select next frame
4461: currentFrame = (StackMapFrame) frames.get(j);
4462: // generate current frame
4463: // need to find differences between the current frame and the previous frame
4464: int frameOffset = currentFrame.pc;
4465: // FULL_FRAME
4466: if (localContentsOffset + 5 >= this .contents.length) {
4467: resizeContents(5);
4468: }
4469: this .contents[localContentsOffset++] = (byte) (frameOffset >> 8);
4470: this .contents[localContentsOffset++] = (byte) frameOffset;
4471: int numberOfLocalOffset = localContentsOffset;
4472: localContentsOffset += 2; // leave two spots for number of locals
4473: int numberOfLocalEntries = 0;
4474: int numberOfLocals = currentFrame
4475: .getNumberOfLocals();
4476: int numberOfEntries = 0;
4477: int localsLength = currentFrame.locals == null ? 0
4478: : currentFrame.locals.length;
4479: for (int i = 0; i < localsLength
4480: && numberOfLocalEntries < numberOfLocals; i++) {
4481: if (localContentsOffset + 3 >= this .contents.length) {
4482: resizeContents(3);
4483: }
4484: VerificationTypeInfo info = currentFrame.locals[i];
4485: if (info == null) {
4486: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4487: } else {
4488: switch (info.id()) {
4489: case T_boolean:
4490: case T_byte:
4491: case T_char:
4492: case T_int:
4493: case T_short:
4494: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4495: break;
4496: case T_float:
4497: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4498: break;
4499: case T_long:
4500: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4501: i++;
4502: break;
4503: case T_double:
4504: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4505: i++;
4506: break;
4507: case T_null:
4508: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4509: break;
4510: default:
4511: this .contents[localContentsOffset++] = (byte) info.tag;
4512: switch (info.tag) {
4513: case VerificationTypeInfo.ITEM_UNINITIALIZED:
4514: int offset = info.offset;
4515: this .contents[localContentsOffset++] = (byte) (offset >> 8);
4516: this .contents[localContentsOffset++] = (byte) offset;
4517: break;
4518: case VerificationTypeInfo.ITEM_OBJECT:
4519: int indexForType = constantPool
4520: .literalIndexForType(info
4521: .constantPoolName());
4522: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
4523: this .contents[localContentsOffset++] = (byte) indexForType;
4524: }
4525: }
4526: numberOfLocalEntries++;
4527: }
4528: numberOfEntries++;
4529: }
4530: if (localContentsOffset + 4 >= this .contents.length) {
4531: resizeContents(4);
4532: }
4533: this .contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
4534: this .contents[numberOfLocalOffset] = (byte) numberOfEntries;
4535: int numberOfStackItems = currentFrame.numberOfStackItems;
4536: this .contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
4537: this .contents[localContentsOffset++] = (byte) numberOfStackItems;
4538: for (int i = 0; i < numberOfStackItems; i++) {
4539: if (localContentsOffset + 3 >= this .contents.length) {
4540: resizeContents(3);
4541: }
4542: VerificationTypeInfo info = currentFrame.stackItems[i];
4543: if (info == null) {
4544: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
4545: } else {
4546: switch (info.id()) {
4547: case T_boolean:
4548: case T_byte:
4549: case T_char:
4550: case T_int:
4551: case T_short:
4552: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
4553: break;
4554: case T_float:
4555: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
4556: break;
4557: case T_long:
4558: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
4559: break;
4560: case T_double:
4561: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
4562: break;
4563: case T_null:
4564: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
4565: break;
4566: default:
4567: this .contents[localContentsOffset++] = (byte) info.tag;
4568: switch (info.tag) {
4569: case VerificationTypeInfo.ITEM_UNINITIALIZED:
4570: int offset = info.offset;
4571: this .contents[localContentsOffset++] = (byte) (offset >> 8);
4572: this .contents[localContentsOffset++] = (byte) offset;
4573: break;
4574: case VerificationTypeInfo.ITEM_OBJECT:
4575: int indexForType = constantPool
4576: .literalIndexForType(info
4577: .constantPoolName());
4578: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
4579: this .contents[localContentsOffset++] = (byte) indexForType;
4580: }
4581: }
4582: }
4583: }
4584: }
4585:
4586: numberOfFrames--;
4587: if (numberOfFrames != 0) {
4588: this .contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
4589: this .contents[numberOfFramesOffset] = (byte) numberOfFrames;
4590:
4591: int attributeLength = localContentsOffset
4592: - stackMapAttributeLengthOffset - 4;
4593: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 24);
4594: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 16);
4595: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 8);
4596: this .contents[stackMapAttributeLengthOffset] = (byte) attributeLength;
4597: attributeNumber++;
4598: } else {
4599: localContentsOffset = stackMapTableAttributeOffset;
4600: }
4601: }
4602: }
4603: }
4604:
4605: // then we do the local variable attribute
4606: // update the number of attributes// ensure first that there is enough space available inside the localContents array
4607: if (codeAttributeAttributeOffset + 2 >= this .contents.length) {
4608: resizeContents(2);
4609: }
4610: this .contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
4611: this .contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
4612: // update the attribute length
4613: int codeAttributeLength = localContentsOffset
4614: - (codeAttributeOffset + 6);
4615: this .contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
4616: this .contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
4617: this .contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
4618: this .contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
4619: contentsOffset = localContentsOffset;
4620: }
4621:
4622: /**
4623: * INTERNAL USE-ONLY
4624: * That method completes the creation of the code attribute by setting
4625: * - the attribute_length
4626: * - max_stack
4627: * - max_locals
4628: * - code_length
4629: * - exception table
4630: * - and debug attributes if necessary.
4631: *
4632: * @param codeAttributeOffset <CODE>int</CODE>
4633: */
4634: public void completeCodeAttributeForProblemMethod(
4635: AbstractMethodDeclaration method, MethodBinding binding,
4636: int codeAttributeOffset, int[] startLineIndexes,
4637: int problemLine) {
4638: // reinitialize the localContents with the byte modified by the code stream
4639: this .contents = codeStream.bCodeStream;
4640: int localContentsOffset = codeStream.classFileOffset;
4641: // 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...
4642: int max_stack = codeStream.stackMax;
4643: this .contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
4644: this .contents[codeAttributeOffset + 7] = (byte) max_stack;
4645: int max_locals = codeStream.maxLocals;
4646: this .contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
4647: this .contents[codeAttributeOffset + 9] = (byte) max_locals;
4648: int code_length = codeStream.position;
4649: this .contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
4650: this .contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
4651: this .contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
4652: this .contents[codeAttributeOffset + 13] = (byte) code_length;
4653: // write the exception table
4654: if (localContentsOffset + 50 >= this .contents.length) {
4655: resizeContents(50);
4656: }
4657:
4658: // write the exception table
4659: this .contents[localContentsOffset++] = 0;
4660: this .contents[localContentsOffset++] = 0;
4661: // debug attributes
4662: int codeAttributeAttributeOffset = localContentsOffset;
4663: int attributeNumber = 0; // leave two bytes for the attribute_length
4664: localContentsOffset += 2; // first we handle the linenumber attribute
4665: if (localContentsOffset + 2 >= this .contents.length) {
4666: resizeContents(2);
4667: }
4668:
4669: if ((this .produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
4670: if (localContentsOffset + 20 >= this .contents.length) {
4671: resizeContents(20);
4672: }
4673: /* Create and add the line number attribute (used for debugging)
4674: * Build the pairs of:
4675: * (bytecodePC lineNumber)
4676: * according to the table of start line indexes and the pcToSourceMap table
4677: * contained into the codestream
4678: */
4679: int lineNumberNameIndex = constantPool
4680: .literalIndex(AttributeNamesConstants.LineNumberTableName);
4681: this .contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
4682: this .contents[localContentsOffset++] = (byte) lineNumberNameIndex;
4683: this .contents[localContentsOffset++] = 0;
4684: this .contents[localContentsOffset++] = 0;
4685: this .contents[localContentsOffset++] = 0;
4686: this .contents[localContentsOffset++] = 6;
4687: this .contents[localContentsOffset++] = 0;
4688: this .contents[localContentsOffset++] = 1;
4689: if (problemLine == 0) {
4690: problemLine = Util.getLineNumber(binding.sourceStart(),
4691: startLineIndexes, 0,
4692: startLineIndexes.length - 1);
4693: }
4694: // first entry at pc = 0
4695: this .contents[localContentsOffset++] = 0;
4696: this .contents[localContentsOffset++] = 0;
4697: this .contents[localContentsOffset++] = (byte) (problemLine >> 8);
4698: this .contents[localContentsOffset++] = (byte) problemLine;
4699: // now we change the size of the line number attribute
4700: attributeNumber++;
4701: }
4702: // then we do the local variable attribute
4703: if ((this .produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
4704: // compute the resolved position for the arguments of the method
4705: int argSize;
4706: int numberOfEntries = 0;
4707: // codeAttribute.addLocalVariableTableAttribute(this);
4708: int localVariableNameIndex = constantPool
4709: .literalIndex(AttributeNamesConstants.LocalVariableTableName);
4710: if (localContentsOffset + 8 >= this .contents.length) {
4711: resizeContents(8);
4712: }
4713: this .contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
4714: this .contents[localContentsOffset++] = (byte) localVariableNameIndex;
4715: int localVariableTableOffset = localContentsOffset;
4716: localContentsOffset += 6;
4717: // leave space for attribute_length and local_variable_table_length
4718: int descriptorIndex;
4719: int nameIndex;
4720: SourceTypeBinding declaringClassBinding = null;
4721: final boolean methodDeclarationIsStatic = codeStream.methodDeclaration
4722: .isStatic();
4723: if (!methodDeclarationIsStatic) {
4724: numberOfEntries++;
4725: if (localContentsOffset + 10 >= this .contents.length) {
4726: resizeContents(10);
4727: }
4728: this .contents[localContentsOffset++] = 0;
4729: this .contents[localContentsOffset++] = 0;
4730: this .contents[localContentsOffset++] = (byte) (code_length >> 8);
4731: this .contents[localContentsOffset++] = (byte) code_length;
4732: nameIndex = constantPool
4733: .literalIndex(ConstantPool.This);
4734: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
4735: this .contents[localContentsOffset++] = (byte) nameIndex;
4736: declaringClassBinding = (SourceTypeBinding) codeStream.methodDeclaration.binding.declaringClass;
4737: descriptorIndex = constantPool
4738: .literalIndex(declaringClassBinding.signature());
4739: this .contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
4740: this .contents[localContentsOffset++] = (byte) descriptorIndex;
4741: // the resolved position for this is always 0
4742: this .contents[localContentsOffset++] = 0;
4743: this .contents[localContentsOffset++] = 0;
4744: }
4745: // used to remember the local variable with a generic type
4746: int genericLocalVariablesCounter = 0;
4747: LocalVariableBinding[] genericLocalVariables = null;
4748: int numberOfGenericEntries = 0;
4749:
4750: if (binding.isConstructor()) {
4751: ReferenceBinding declaringClass = binding.declaringClass;
4752: if (declaringClass.isNestedType()) {
4753: NestedTypeBinding methodDeclaringClass = (NestedTypeBinding) declaringClass;
4754: argSize = methodDeclaringClass.enclosingInstancesSlotSize;
4755: SyntheticArgumentBinding[] syntheticArguments;
4756: if ((syntheticArguments = methodDeclaringClass
4757: .syntheticEnclosingInstances()) != null) {
4758: for (int i = 0, max = syntheticArguments.length; i < max; i++) {
4759: LocalVariableBinding localVariable = syntheticArguments[i];
4760: final TypeBinding localVariableTypeBinding = localVariable.type;
4761: if (localVariableTypeBinding
4762: .isParameterizedType()
4763: || localVariableTypeBinding
4764: .isTypeVariable()) {
4765: if (genericLocalVariables == null) {
4766: // we cannot have more than max locals
4767: genericLocalVariables = new LocalVariableBinding[max];
4768: }
4769: genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
4770: numberOfGenericEntries++;
4771: }
4772: if (localContentsOffset + 10 >= this .contents.length) {
4773: resizeContents(10);
4774: }
4775: // now we can safely add the local entry
4776: numberOfEntries++;
4777: this .contents[localContentsOffset++] = 0;
4778: this .contents[localContentsOffset++] = 0;
4779: this .contents[localContentsOffset++] = (byte) (code_length >> 8);
4780: this .contents[localContentsOffset++] = (byte) code_length;
4781: nameIndex = constantPool
4782: .literalIndex(localVariable.name);
4783: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
4784: this .contents[localContentsOffset++] = (byte) nameIndex;
4785: descriptorIndex = constantPool
4786: .literalIndex(localVariableTypeBinding
4787: .signature());
4788: this .contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
4789: this .contents[localContentsOffset++] = (byte) descriptorIndex;
4790: int resolvedPosition = localVariable.resolvedPosition;
4791: this .contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
4792: this .contents[localContentsOffset++] = (byte) resolvedPosition;
4793: }
4794: }
4795: } else {
4796: argSize = 1;
4797: }
4798: } else {
4799: argSize = binding.isStatic() ? 0 : 1;
4800: }
4801:
4802: int genericArgumentsCounter = 0;
4803: int[] genericArgumentsNameIndexes = null;
4804: int[] genericArgumentsResolvedPositions = null;
4805: TypeBinding[] genericArgumentsTypeBindings = null;
4806:
4807: if (method.binding != null) {
4808: TypeBinding[] parameters = method.binding.parameters;
4809: Argument[] arguments = method.arguments;
4810: if ((parameters != null) && (arguments != null)) {
4811: for (int i = 0, max = parameters.length; i < max; i++) {
4812: TypeBinding argumentBinding = parameters[i];
4813: if (localContentsOffset + 10 >= this .contents.length) {
4814: resizeContents(10);
4815: }
4816: // now we can safely add the local entry
4817: numberOfEntries++;
4818: this .contents[localContentsOffset++] = 0;
4819: this .contents[localContentsOffset++] = 0;
4820: this .contents[localContentsOffset++] = (byte) (code_length >> 8);
4821: this .contents[localContentsOffset++] = (byte) code_length;
4822: nameIndex = constantPool
4823: .literalIndex(arguments[i].name);
4824: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
4825: this .contents[localContentsOffset++] = (byte) nameIndex;
4826: int resolvedPosition = argSize;
4827: if (argumentBinding.isParameterizedType()
4828: || argumentBinding.isTypeVariable()) {
4829: if (genericArgumentsCounter == 0) {
4830: // we cannot have more than max locals
4831: genericArgumentsNameIndexes = new int[max];
4832: genericArgumentsResolvedPositions = new int[max];
4833: genericArgumentsTypeBindings = new TypeBinding[max];
4834: }
4835: genericArgumentsNameIndexes[genericArgumentsCounter] = nameIndex;
4836: genericArgumentsResolvedPositions[genericArgumentsCounter] = resolvedPosition;
4837: genericArgumentsTypeBindings[genericArgumentsCounter++] = argumentBinding;
4838: }
4839: descriptorIndex = constantPool
4840: .literalIndex(argumentBinding
4841: .signature());
4842: this .contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
4843: this .contents[localContentsOffset++] = (byte) descriptorIndex;
4844: if ((argumentBinding == TypeBinding.LONG)
4845: || (argumentBinding == TypeBinding.DOUBLE))
4846: argSize += 2;
4847: else
4848: argSize++;
4849: this .contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
4850: this .contents[localContentsOffset++] = (byte) resolvedPosition;
4851: }
4852: }
4853: }
4854: int value = numberOfEntries * 10 + 2;
4855: this .contents[localVariableTableOffset++] = (byte) (value >> 24);
4856: this .contents[localVariableTableOffset++] = (byte) (value >> 16);
4857: this .contents[localVariableTableOffset++] = (byte) (value >> 8);
4858: this .contents[localVariableTableOffset++] = (byte) value;
4859: this .contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
4860: this .contents[localVariableTableOffset] = (byte) numberOfEntries;
4861: attributeNumber++;
4862:
4863: final boolean currentInstanceIsGeneric = !methodDeclarationIsStatic
4864: && declaringClassBinding != null
4865: && declaringClassBinding.typeVariables != Binding.NO_TYPE_VARIABLES;
4866: if (genericLocalVariablesCounter != 0
4867: || genericArgumentsCounter != 0
4868: || currentInstanceIsGeneric) {
4869: // add the local variable type table attribute
4870: numberOfEntries = numberOfGenericEntries
4871: + genericArgumentsCounter
4872: + (currentInstanceIsGeneric ? 1 : 0);
4873: // reserve enough space
4874: int maxOfEntries = 8 + numberOfEntries * 10;
4875: if (localContentsOffset + maxOfEntries >= this .contents.length) {
4876: resizeContents(maxOfEntries);
4877: }
4878: int localVariableTypeNameIndex = constantPool
4879: .literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
4880: this .contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
4881: this .contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
4882: value = numberOfEntries * 10 + 2;
4883: this .contents[localContentsOffset++] = (byte) (value >> 24);
4884: this .contents[localContentsOffset++] = (byte) (value >> 16);
4885: this .contents[localContentsOffset++] = (byte) (value >> 8);
4886: this .contents[localContentsOffset++] = (byte) value;
4887: this .contents[localContentsOffset++] = (byte) (numberOfEntries >> 8);
4888: this .contents[localContentsOffset++] = (byte) numberOfEntries;
4889: if (currentInstanceIsGeneric) {
4890: numberOfEntries++;
4891: this .contents[localContentsOffset++] = 0; // the startPC for this is always 0
4892: this .contents[localContentsOffset++] = 0;
4893: this .contents[localContentsOffset++] = (byte) (code_length >> 8);
4894: this .contents[localContentsOffset++] = (byte) code_length;
4895: nameIndex = constantPool
4896: .literalIndex(ConstantPool.This);
4897: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
4898: this .contents[localContentsOffset++] = (byte) nameIndex;
4899: descriptorIndex = constantPool
4900: .literalIndex(declaringClassBinding
4901: .genericTypeSignature());
4902: this .contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
4903: this .contents[localContentsOffset++] = (byte) descriptorIndex;
4904: this .contents[localContentsOffset++] = 0;// the resolved position for this is always 0
4905: this .contents[localContentsOffset++] = 0;
4906: }
4907:
4908: for (int i = 0; i < genericLocalVariablesCounter; i++) {
4909: LocalVariableBinding localVariable = genericLocalVariables[i];
4910: this .contents[localContentsOffset++] = 0;
4911: this .contents[localContentsOffset++] = 0;
4912: this .contents[localContentsOffset++] = (byte) (code_length >> 8);
4913: this .contents[localContentsOffset++] = (byte) code_length;
4914: nameIndex = constantPool
4915: .literalIndex(localVariable.name);
4916: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
4917: this .contents[localContentsOffset++] = (byte) nameIndex;
4918: descriptorIndex = constantPool
4919: .literalIndex(localVariable.type
4920: .genericTypeSignature());
4921: this .contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
4922: this .contents[localContentsOffset++] = (byte) descriptorIndex;
4923: int resolvedPosition = localVariable.resolvedPosition;
4924: this .contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
4925: this .contents[localContentsOffset++] = (byte) resolvedPosition;
4926: }
4927: for (int i = 0; i < genericArgumentsCounter; i++) {
4928: this .contents[localContentsOffset++] = 0;
4929: this .contents[localContentsOffset++] = 0;
4930: this .contents[localContentsOffset++] = (byte) (code_length >> 8);
4931: this .contents[localContentsOffset++] = (byte) code_length;
4932: nameIndex = genericArgumentsNameIndexes[i];
4933: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
4934: this .contents[localContentsOffset++] = (byte) nameIndex;
4935: descriptorIndex = constantPool
4936: .literalIndex(genericArgumentsTypeBindings[i]
4937: .genericTypeSignature());
4938: this .contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
4939: this .contents[localContentsOffset++] = (byte) descriptorIndex;
4940: int resolvedPosition = genericArgumentsResolvedPositions[i];
4941: this .contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
4942: this .contents[localContentsOffset++] = (byte) resolvedPosition;
4943: }
4944: attributeNumber++;
4945: }
4946: }
4947:
4948: if ((this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) {
4949: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
4950: stackMapFrameCodeStream.removeFramePosition(code_length);
4951: if (stackMapFrameCodeStream.hasFramePositions()) {
4952: ArrayList frames = new ArrayList();
4953: traverse(binding, max_locals, this .contents,
4954: codeAttributeOffset + 14, code_length, frames,
4955: false);
4956: int numberOfFrames = frames.size();
4957: if (numberOfFrames > 1) {
4958: int stackMapTableAttributeOffset = localContentsOffset;
4959: // add the stack map table attribute
4960: if (localContentsOffset + 8 >= this .contents.length) {
4961: resizeContents(8);
4962: }
4963: int stackMapTableAttributeNameIndex = constantPool
4964: .literalIndex(AttributeNamesConstants.StackMapTableName);
4965: this .contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
4966: this .contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
4967:
4968: int stackMapTableAttributeLengthOffset = localContentsOffset;
4969: // generate the attribute
4970: localContentsOffset += 4;
4971: if (localContentsOffset + 4 >= this .contents.length) {
4972: resizeContents(4);
4973: }
4974: numberOfFrames = 0;
4975: int numberOfFramesOffset = localContentsOffset;
4976: localContentsOffset += 2;
4977: if (localContentsOffset + 2 >= this .contents.length) {
4978: resizeContents(2);
4979: }
4980: StackMapFrame currentFrame = (StackMapFrame) frames
4981: .get(0);
4982: StackMapFrame prevFrame = null;
4983: for (int j = 1; j < numberOfFrames; j++) {
4984: // select next frame
4985: prevFrame = currentFrame;
4986: currentFrame = (StackMapFrame) frames.get(j);
4987: // generate current frame
4988: // need to find differences between the current frame and the previous frame
4989: numberOfFrames++;
4990: int offsetDelta = currentFrame
4991: .getOffsetDelta(prevFrame);
4992: switch (currentFrame.getFrameType(prevFrame)) {
4993: case StackMapFrame.APPEND_FRAME:
4994: if (localContentsOffset + 3 >= this .contents.length) {
4995: resizeContents(3);
4996: }
4997: int numberOfDifferentLocals = currentFrame
4998: .numberOfDifferentLocals(prevFrame);
4999: this .contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
5000: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
5001: this .contents[localContentsOffset++] = (byte) offsetDelta;
5002: int index = currentFrame
5003: .getIndexOfDifferentLocals(numberOfDifferentLocals);
5004: int numberOfLocals = currentFrame
5005: .getNumberOfLocals();
5006: for (int i = index; i < currentFrame.locals.length
5007: && numberOfDifferentLocals > 0; i++) {
5008: if (localContentsOffset + 6 >= this .contents.length) {
5009: resizeContents(6);
5010: }
5011: VerificationTypeInfo info = currentFrame.locals[i];
5012: if (info == null) {
5013: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
5014: } else {
5015: switch (info.id()) {
5016: case T_boolean:
5017: case T_byte:
5018: case T_char:
5019: case T_int:
5020: case T_short:
5021: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
5022: break;
5023: case T_float:
5024: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
5025: break;
5026: case T_long:
5027: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
5028: i++;
5029: break;
5030: case T_double:
5031: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
5032: i++;
5033: break;
5034: case T_null:
5035: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
5036: break;
5037: default:
5038: this .contents[localContentsOffset++] = (byte) info.tag;
5039: switch (info.tag) {
5040: case VerificationTypeInfo.ITEM_UNINITIALIZED:
5041: int offset = info.offset;
5042: this .contents[localContentsOffset++] = (byte) (offset >> 8);
5043: this .contents[localContentsOffset++] = (byte) offset;
5044: break;
5045: case VerificationTypeInfo.ITEM_OBJECT:
5046: int indexForType = constantPool
5047: .literalIndexForType(info
5048: .constantPoolName());
5049: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
5050: this .contents[localContentsOffset++] = (byte) indexForType;
5051: }
5052: }
5053: numberOfDifferentLocals--;
5054: }
5055: }
5056: break;
5057: case StackMapFrame.SAME_FRAME:
5058: if (localContentsOffset + 1 >= this .contents.length) {
5059: resizeContents(1);
5060: }
5061: this .contents[localContentsOffset++] = (byte) offsetDelta;
5062: break;
5063: case StackMapFrame.SAME_FRAME_EXTENDED:
5064: if (localContentsOffset + 3 >= this .contents.length) {
5065: resizeContents(3);
5066: }
5067: this .contents[localContentsOffset++] = (byte) 251;
5068: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
5069: this .contents[localContentsOffset++] = (byte) offsetDelta;
5070: break;
5071: case StackMapFrame.CHOP_FRAME:
5072: if (localContentsOffset + 3 >= this .contents.length) {
5073: resizeContents(3);
5074: }
5075: numberOfDifferentLocals = -currentFrame
5076: .numberOfDifferentLocals(prevFrame);
5077: this .contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
5078: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
5079: this .contents[localContentsOffset++] = (byte) offsetDelta;
5080: break;
5081: case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS:
5082: if (localContentsOffset + 4 >= this .contents.length) {
5083: resizeContents(4);
5084: }
5085: this .contents[localContentsOffset++] = (byte) (offsetDelta + 64);
5086: if (currentFrame.stackItems[0] == null) {
5087: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
5088: } else {
5089: switch (currentFrame.stackItems[0].id()) {
5090: case T_boolean:
5091: case T_byte:
5092: case T_char:
5093: case T_int:
5094: case T_short:
5095: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
5096: break;
5097: case T_float:
5098: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
5099: break;
5100: case T_long:
5101: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
5102: break;
5103: case T_double:
5104: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
5105: break;
5106: case T_null:
5107: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
5108: break;
5109: default:
5110: VerificationTypeInfo info = currentFrame.stackItems[0];
5111: byte tag = (byte) info.tag;
5112: this .contents[localContentsOffset++] = tag;
5113: switch (tag) {
5114: case VerificationTypeInfo.ITEM_UNINITIALIZED:
5115: int offset = info.offset;
5116: this .contents[localContentsOffset++] = (byte) (offset >> 8);
5117: this .contents[localContentsOffset++] = (byte) offset;
5118: break;
5119: case VerificationTypeInfo.ITEM_OBJECT:
5120: int indexForType = constantPool
5121: .literalIndexForType(info
5122: .constantPoolName());
5123: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
5124: this .contents[localContentsOffset++] = (byte) indexForType;
5125: }
5126: }
5127: }
5128: break;
5129: case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED:
5130: if (localContentsOffset + 6 >= this .contents.length) {
5131: resizeContents(6);
5132: }
5133: this .contents[localContentsOffset++] = (byte) 247;
5134: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
5135: this .contents[localContentsOffset++] = (byte) offsetDelta;
5136: if (currentFrame.stackItems[0] == null) {
5137: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
5138: } else {
5139: switch (currentFrame.stackItems[0].id()) {
5140: case T_boolean:
5141: case T_byte:
5142: case T_char:
5143: case T_int:
5144: case T_short:
5145: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
5146: break;
5147: case T_float:
5148: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
5149: break;
5150: case T_long:
5151: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
5152: break;
5153: case T_double:
5154: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
5155: break;
5156: case T_null:
5157: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
5158: break;
5159: default:
5160: VerificationTypeInfo info = currentFrame.stackItems[0];
5161: byte tag = (byte) info.tag;
5162: this .contents[localContentsOffset++] = tag;
5163: switch (tag) {
5164: case VerificationTypeInfo.ITEM_UNINITIALIZED:
5165: int offset = info.offset;
5166: this .contents[localContentsOffset++] = (byte) (offset >> 8);
5167: this .contents[localContentsOffset++] = (byte) offset;
5168: break;
5169: case VerificationTypeInfo.ITEM_OBJECT:
5170: int indexForType = constantPool
5171: .literalIndexForType(info
5172: .constantPoolName());
5173: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
5174: this .contents[localContentsOffset++] = (byte) indexForType;
5175: }
5176: }
5177: }
5178: break;
5179: default:
5180: // FULL_FRAME
5181: if (localContentsOffset + 5 >= this .contents.length) {
5182: resizeContents(5);
5183: }
5184: this .contents[localContentsOffset++] = (byte) 255;
5185: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
5186: this .contents[localContentsOffset++] = (byte) offsetDelta;
5187: int numberOfLocalOffset = localContentsOffset;
5188: localContentsOffset += 2; // leave two spots for number of locals
5189: int numberOfLocalEntries = 0;
5190: numberOfLocals = currentFrame
5191: .getNumberOfLocals();
5192: int numberOfEntries = 0;
5193: int localsLength = currentFrame.locals == null ? 0
5194: : currentFrame.locals.length;
5195: for (int i = 0; i < localsLength
5196: && numberOfLocalEntries < numberOfLocals; i++) {
5197: if (localContentsOffset + 3 >= this .contents.length) {
5198: resizeContents(3);
5199: }
5200: VerificationTypeInfo info = currentFrame.locals[i];
5201: if (info == null) {
5202: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
5203: } else {
5204: switch (info.id()) {
5205: case T_boolean:
5206: case T_byte:
5207: case T_char:
5208: case T_int:
5209: case T_short:
5210: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
5211: break;
5212: case T_float:
5213: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
5214: break;
5215: case T_long:
5216: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
5217: i++;
5218: break;
5219: case T_double:
5220: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
5221: i++;
5222: break;
5223: case T_null:
5224: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
5225: break;
5226: default:
5227: this .contents[localContentsOffset++] = (byte) info.tag;
5228: switch (info.tag) {
5229: case VerificationTypeInfo.ITEM_UNINITIALIZED:
5230: int offset = info.offset;
5231: this .contents[localContentsOffset++] = (byte) (offset >> 8);
5232: this .contents[localContentsOffset++] = (byte) offset;
5233: break;
5234: case VerificationTypeInfo.ITEM_OBJECT:
5235: int indexForType = constantPool
5236: .literalIndexForType(info
5237: .constantPoolName());
5238: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
5239: this .contents[localContentsOffset++] = (byte) indexForType;
5240: }
5241: }
5242: numberOfLocalEntries++;
5243: }
5244: numberOfEntries++;
5245: }
5246: if (localContentsOffset + 4 >= this .contents.length) {
5247: resizeContents(4);
5248: }
5249: this .contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
5250: this .contents[numberOfLocalOffset] = (byte) numberOfEntries;
5251: int numberOfStackItems = currentFrame.numberOfStackItems;
5252: this .contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
5253: this .contents[localContentsOffset++] = (byte) numberOfStackItems;
5254: for (int i = 0; i < numberOfStackItems; i++) {
5255: if (localContentsOffset + 3 >= this .contents.length) {
5256: resizeContents(3);
5257: }
5258: VerificationTypeInfo info = currentFrame.stackItems[i];
5259: if (info == null) {
5260: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
5261: } else {
5262: switch (info.id()) {
5263: case T_boolean:
5264: case T_byte:
5265: case T_char:
5266: case T_int:
5267: case T_short:
5268: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
5269: break;
5270: case T_float:
5271: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
5272: break;
5273: case T_long:
5274: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
5275: break;
5276: case T_double:
5277: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
5278: break;
5279: case T_null:
5280: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
5281: break;
5282: default:
5283: this .contents[localContentsOffset++] = (byte) info.tag;
5284: switch (info.tag) {
5285: case VerificationTypeInfo.ITEM_UNINITIALIZED:
5286: int offset = info.offset;
5287: this .contents[localContentsOffset++] = (byte) (offset >> 8);
5288: this .contents[localContentsOffset++] = (byte) offset;
5289: break;
5290: case VerificationTypeInfo.ITEM_OBJECT:
5291: int indexForType = constantPool
5292: .literalIndexForType(info
5293: .constantPoolName());
5294: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
5295: this .contents[localContentsOffset++] = (byte) indexForType;
5296: }
5297: }
5298: }
5299: }
5300: }
5301: }
5302:
5303: if (numberOfFrames != 0) {
5304: this .contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
5305: this .contents[numberOfFramesOffset] = (byte) numberOfFrames;
5306:
5307: int attributeLength = localContentsOffset
5308: - stackMapTableAttributeLengthOffset
5309: - 4;
5310: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
5311: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
5312: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
5313: this .contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
5314: attributeNumber++;
5315: } else {
5316: localContentsOffset = stackMapTableAttributeOffset;
5317: }
5318: }
5319: }
5320: }
5321:
5322: if ((this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
5323: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
5324: stackMapFrameCodeStream.removeFramePosition(code_length);
5325: if (stackMapFrameCodeStream.hasFramePositions()) {
5326: ArrayList frames = new ArrayList();
5327: traverse(this .codeStream.methodDeclaration.binding,
5328: max_locals, this .contents,
5329: codeAttributeOffset + 14, code_length, frames,
5330: false);
5331: int numberOfFrames = frames.size();
5332: if (numberOfFrames > 1) {
5333: int stackMapTableAttributeOffset = localContentsOffset;
5334: // add the stack map table attribute
5335: if (localContentsOffset + 8 >= this .contents.length) {
5336: resizeContents(8);
5337: }
5338: int stackMapAttributeNameIndex = constantPool
5339: .literalIndex(AttributeNamesConstants.StackMapName);
5340: this .contents[localContentsOffset++] = (byte) (stackMapAttributeNameIndex >> 8);
5341: this .contents[localContentsOffset++] = (byte) stackMapAttributeNameIndex;
5342:
5343: int stackMapAttributeLengthOffset = localContentsOffset;
5344: // generate the attribute
5345: localContentsOffset += 4;
5346: if (localContentsOffset + 4 >= this .contents.length) {
5347: resizeContents(4);
5348: }
5349: int numberOfFramesOffset = localContentsOffset;
5350: localContentsOffset += 2;
5351: if (localContentsOffset + 2 >= this .contents.length) {
5352: resizeContents(2);
5353: }
5354: StackMapFrame currentFrame = (StackMapFrame) frames
5355: .get(0);
5356: for (int j = 1; j < numberOfFrames; j++) {
5357: // select next frame
5358: currentFrame = (StackMapFrame) frames.get(j);
5359: // generate current frame
5360: // need to find differences between the current frame and the previous frame
5361: int frameOffset = currentFrame.pc;
5362: // FULL_FRAME
5363: if (localContentsOffset + 5 >= this .contents.length) {
5364: resizeContents(5);
5365: }
5366: this .contents[localContentsOffset++] = (byte) (frameOffset >> 8);
5367: this .contents[localContentsOffset++] = (byte) frameOffset;
5368: int numberOfLocalOffset = localContentsOffset;
5369: localContentsOffset += 2; // leave two spots for number of locals
5370: int numberOfLocalEntries = 0;
5371: int numberOfLocals = currentFrame
5372: .getNumberOfLocals();
5373: int numberOfEntries = 0;
5374: int localsLength = currentFrame.locals == null ? 0
5375: : currentFrame.locals.length;
5376: for (int i = 0; i < localsLength
5377: && numberOfLocalEntries < numberOfLocals; i++) {
5378: if (localContentsOffset + 3 >= this .contents.length) {
5379: resizeContents(3);
5380: }
5381: VerificationTypeInfo info = currentFrame.locals[i];
5382: if (info == null) {
5383: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
5384: } else {
5385: switch (info.id()) {
5386: case T_boolean:
5387: case T_byte:
5388: case T_char:
5389: case T_int:
5390: case T_short:
5391: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
5392: break;
5393: case T_float:
5394: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
5395: break;
5396: case T_long:
5397: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
5398: i++;
5399: break;
5400: case T_double:
5401: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
5402: i++;
5403: break;
5404: case T_null:
5405: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
5406: break;
5407: default:
5408: this .contents[localContentsOffset++] = (byte) info.tag;
5409: switch (info.tag) {
5410: case VerificationTypeInfo.ITEM_UNINITIALIZED:
5411: int offset = info.offset;
5412: this .contents[localContentsOffset++] = (byte) (offset >> 8);
5413: this .contents[localContentsOffset++] = (byte) offset;
5414: break;
5415: case VerificationTypeInfo.ITEM_OBJECT:
5416: int indexForType = constantPool
5417: .literalIndexForType(info
5418: .constantPoolName());
5419: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
5420: this .contents[localContentsOffset++] = (byte) indexForType;
5421: }
5422: }
5423: numberOfLocalEntries++;
5424: }
5425: numberOfEntries++;
5426: }
5427: if (localContentsOffset + 4 >= this .contents.length) {
5428: resizeContents(4);
5429: }
5430: this .contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
5431: this .contents[numberOfLocalOffset] = (byte) numberOfEntries;
5432: int numberOfStackItems = currentFrame.numberOfStackItems;
5433: this .contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
5434: this .contents[localContentsOffset++] = (byte) numberOfStackItems;
5435: for (int i = 0; i < numberOfStackItems; i++) {
5436: if (localContentsOffset + 3 >= this .contents.length) {
5437: resizeContents(3);
5438: }
5439: VerificationTypeInfo info = currentFrame.stackItems[i];
5440: if (info == null) {
5441: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
5442: } else {
5443: switch (info.id()) {
5444: case T_boolean:
5445: case T_byte:
5446: case T_char:
5447: case T_int:
5448: case T_short:
5449: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
5450: break;
5451: case T_float:
5452: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
5453: break;
5454: case T_long:
5455: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
5456: break;
5457: case T_double:
5458: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
5459: break;
5460: case T_null:
5461: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
5462: break;
5463: default:
5464: this .contents[localContentsOffset++] = (byte) info.tag;
5465: switch (info.tag) {
5466: case VerificationTypeInfo.ITEM_UNINITIALIZED:
5467: int offset = info.offset;
5468: this .contents[localContentsOffset++] = (byte) (offset >> 8);
5469: this .contents[localContentsOffset++] = (byte) offset;
5470: break;
5471: case VerificationTypeInfo.ITEM_OBJECT:
5472: int indexForType = constantPool
5473: .literalIndexForType(info
5474: .constantPoolName());
5475: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
5476: this .contents[localContentsOffset++] = (byte) indexForType;
5477: }
5478: }
5479: }
5480: }
5481: }
5482:
5483: numberOfFrames--;
5484: if (numberOfFrames != 0) {
5485: this .contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
5486: this .contents[numberOfFramesOffset] = (byte) numberOfFrames;
5487:
5488: int attributeLength = localContentsOffset
5489: - stackMapAttributeLengthOffset - 4;
5490: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 24);
5491: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 16);
5492: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 8);
5493: this .contents[stackMapAttributeLengthOffset] = (byte) attributeLength;
5494: attributeNumber++;
5495: } else {
5496: localContentsOffset = stackMapTableAttributeOffset;
5497: }
5498: }
5499: }
5500: }
5501:
5502: // update the number of attributes// ensure first that there is enough space available inside the localContents array
5503: if (codeAttributeAttributeOffset + 2 >= this .contents.length) {
5504: resizeContents(2);
5505: }
5506: this .contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
5507: this .contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
5508: // update the attribute length
5509: int codeAttributeLength = localContentsOffset
5510: - (codeAttributeOffset + 6);
5511: this .contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
5512: this .contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
5513: this .contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
5514: this .contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
5515: contentsOffset = localContentsOffset;
5516: }
5517:
5518: /**
5519: * INTERNAL USE-ONLY
5520: * That method completes the creation of the code attribute by setting
5521: * - the attribute_length
5522: * - max_stack
5523: * - max_locals
5524: * - code_length
5525: * - exception table
5526: * - and debug attributes if necessary.
5527: *
5528: * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
5529: * @param codeAttributeOffset <CODE>int</CODE>
5530: */
5531: public void completeCodeAttributeForSyntheticMethod(
5532: boolean hasExceptionHandlers,
5533: SyntheticMethodBinding binding, int codeAttributeOffset,
5534: int[] startLineIndexes) {
5535: // reinitialize the contents with the byte modified by the code stream
5536: this .contents = codeStream.bCodeStream;
5537: int localContentsOffset = codeStream.classFileOffset;
5538: // codeAttributeOffset is the position inside contents byte array before we started to write
5539: // any information about the codeAttribute
5540: // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset
5541: // to get the right position, 6 for the max_stack etc...
5542: int max_stack = codeStream.stackMax;
5543: contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8);
5544: contents[codeAttributeOffset + 7] = (byte) max_stack;
5545: int max_locals = codeStream.maxLocals;
5546: contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8);
5547: contents[codeAttributeOffset + 9] = (byte) max_locals;
5548: int code_length = codeStream.position;
5549: contents[codeAttributeOffset + 10] = (byte) (code_length >> 24);
5550: contents[codeAttributeOffset + 11] = (byte) (code_length >> 16);
5551: contents[codeAttributeOffset + 12] = (byte) (code_length >> 8);
5552: contents[codeAttributeOffset + 13] = (byte) code_length;
5553: if ((localContentsOffset + 40) >= this .contents.length) {
5554: resizeContents(40);
5555: }
5556:
5557: boolean addStackMaps = (this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0;
5558: if (hasExceptionHandlers) {
5559: // write the exception table
5560: ExceptionLabel[] exceptionLabels = codeStream.exceptionLabels;
5561: int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous)
5562: for (int i = 0, length = codeStream.exceptionLabelsCounter; i < length; i++) {
5563: exceptionHandlersCount += codeStream.exceptionLabels[i].count / 2;
5564: }
5565: int exSize = exceptionHandlersCount * 8 + 2;
5566: if (exSize + localContentsOffset >= this .contents.length) {
5567: resizeContents(exSize);
5568: }
5569: // there is no exception table, so we need to offset by 2 the current offset and move
5570: // on the attribute generation
5571: this .contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8);
5572: this .contents[localContentsOffset++] = (byte) exceptionHandlersCount;
5573: for (int i = 0, max = codeStream.exceptionLabelsCounter; i < max; i++) {
5574: ExceptionLabel exceptionLabel = exceptionLabels[i];
5575: if (exceptionLabel != null) {
5576: int iRange = 0, maxRange = exceptionLabel.count;
5577: if ((maxRange & 1) != 0) {
5578: referenceBinding.scope
5579: .problemReporter()
5580: .abortDueToInternalError(
5581: Messages
5582: .bind(
5583: Messages.abort_invalidExceptionAttribute,
5584: new String(
5585: binding.selector),
5586: referenceBinding.scope
5587: .problemReporter().referenceContext));
5588: }
5589: while (iRange < maxRange) {
5590: int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions
5591: this .contents[localContentsOffset++] = (byte) (start >> 8);
5592: this .contents[localContentsOffset++] = (byte) start;
5593: int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions
5594: this .contents[localContentsOffset++] = (byte) (end >> 8);
5595: this .contents[localContentsOffset++] = (byte) end;
5596: int handlerPC = exceptionLabel.position;
5597: if (addStackMaps) {
5598: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
5599: stackMapFrameCodeStream
5600: .addFramePosition(handlerPC);
5601: // stackMapFrameCodeStream.addExceptionMarker(handlerPC, exceptionLabel.exceptionType);
5602: }
5603: this .contents[localContentsOffset++] = (byte) (handlerPC >> 8);
5604: this .contents[localContentsOffset++] = (byte) handlerPC;
5605: if (exceptionLabel.exceptionType == null) {
5606: // any exception handler
5607: this .contents[localContentsOffset++] = 0;
5608: this .contents[localContentsOffset++] = 0;
5609: } else {
5610: int nameIndex;
5611: switch (exceptionLabel.exceptionType.id) {
5612: case T_null:
5613: /* represents ClassNotFoundException, see class literal access*/
5614: nameIndex = constantPool
5615: .literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName);
5616: break;
5617: case T_long:
5618: /* represents NoSuchFieldError, see switch table generation*/
5619: nameIndex = constantPool
5620: .literalIndexForType(ConstantPool.JavaLangNoSuchFieldErrorConstantPoolName);
5621: break;
5622: default:
5623: nameIndex = constantPool
5624: .literalIndexForType(exceptionLabel.exceptionType);
5625: }
5626: this .contents[localContentsOffset++] = (byte) (nameIndex >> 8);
5627: this .contents[localContentsOffset++] = (byte) nameIndex;
5628: }
5629: }
5630: }
5631: }
5632: } else {
5633: // there is no exception table, so we need to offset by 2 the current offset and move
5634: // on the attribute generation
5635: contents[localContentsOffset++] = 0;
5636: contents[localContentsOffset++] = 0;
5637: }
5638: // debug attributes
5639: int codeAttributeAttributeOffset = localContentsOffset;
5640: int attributeNumber = 0;
5641: // leave two bytes for the attribute_length
5642: localContentsOffset += 2;
5643: if (localContentsOffset + 2 >= this .contents.length) {
5644: resizeContents(2);
5645: }
5646:
5647: // first we handle the linenumber attribute
5648: if ((this .produceAttributes & ClassFileConstants.ATTR_LINES) != 0) {
5649: if (localContentsOffset + 12 >= this .contents.length) {
5650: resizeContents(12);
5651: }
5652: int index = 0;
5653: int lineNumberNameIndex = constantPool
5654: .literalIndex(AttributeNamesConstants.LineNumberTableName);
5655: contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8);
5656: contents[localContentsOffset++] = (byte) lineNumberNameIndex;
5657: int lineNumberTableOffset = localContentsOffset;
5658: localContentsOffset += 6;
5659: // leave space for attribute_length and line_number_table_length
5660: // Seems like do would be better, but this preserves the existing behavior.
5661: index = Util.getLineNumber(binding.sourceStart,
5662: startLineIndexes, 0, startLineIndexes.length - 1);
5663: contents[localContentsOffset++] = 0;
5664: contents[localContentsOffset++] = 0;
5665: contents[localContentsOffset++] = (byte) (index >> 8);
5666: contents[localContentsOffset++] = (byte) index;
5667: // now we change the size of the line number attribute
5668: contents[lineNumberTableOffset++] = 0;
5669: contents[lineNumberTableOffset++] = 0;
5670: contents[lineNumberTableOffset++] = 0;
5671: contents[lineNumberTableOffset++] = 6;
5672: contents[lineNumberTableOffset++] = 0;
5673: contents[lineNumberTableOffset++] = 1;
5674: attributeNumber++;
5675: }
5676: // then we do the local variable attribute
5677: if ((this .produceAttributes & ClassFileConstants.ATTR_VARS) != 0) {
5678: int numberOfEntries = 0;
5679: int localVariableNameIndex = constantPool
5680: .literalIndex(AttributeNamesConstants.LocalVariableTableName);
5681: if (localContentsOffset + 8 > this .contents.length) {
5682: resizeContents(8);
5683: }
5684: contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8);
5685: contents[localContentsOffset++] = (byte) localVariableNameIndex;
5686: int localVariableTableOffset = localContentsOffset;
5687: localContentsOffset += 6;
5688: // leave space for attribute_length and local_variable_table_length
5689: int nameIndex;
5690: int descriptorIndex;
5691:
5692: // used to remember the local variable with a generic type
5693: int genericLocalVariablesCounter = 0;
5694: LocalVariableBinding[] genericLocalVariables = null;
5695: int numberOfGenericEntries = 0;
5696:
5697: for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
5698: LocalVariableBinding localVariable = codeStream.locals[i];
5699: if (localVariable.declaration == null)
5700: continue;
5701: final TypeBinding localVariableTypeBinding = localVariable.type;
5702: boolean isParameterizedType = localVariableTypeBinding
5703: .isParameterizedType()
5704: || localVariableTypeBinding.isTypeVariable();
5705: if (localVariable.initializationCount != 0
5706: && isParameterizedType) {
5707: if (genericLocalVariables == null) {
5708: // we cannot have more than max locals
5709: genericLocalVariables = new LocalVariableBinding[max];
5710: }
5711: genericLocalVariables[genericLocalVariablesCounter++] = localVariable;
5712: }
5713: for (int j = 0; j < localVariable.initializationCount; j++) {
5714: int startPC = localVariable.initializationPCs[j << 1];
5715: int endPC = localVariable.initializationPCs[(j << 1) + 1];
5716: if (startPC != endPC) { // only entries for non zero length
5717: if (endPC == -1) {
5718: localVariable.declaringScope
5719: .problemReporter()
5720: .abortDueToInternalError(
5721: Messages
5722: .bind(
5723: Messages.abort_invalidAttribute,
5724: new String(
5725: localVariable.name)),
5726: (ASTNode) localVariable.declaringScope
5727: .methodScope().referenceContext);
5728: }
5729: if (localContentsOffset + 10 > this .contents.length) {
5730: resizeContents(10);
5731: }
5732: // now we can safely add the local entry
5733: numberOfEntries++;
5734: if (isParameterizedType) {
5735: numberOfGenericEntries++;
5736: }
5737: contents[localContentsOffset++] = (byte) (startPC >> 8);
5738: contents[localContentsOffset++] = (byte) startPC;
5739: int length = endPC - startPC;
5740: contents[localContentsOffset++] = (byte) (length >> 8);
5741: contents[localContentsOffset++] = (byte) length;
5742: nameIndex = constantPool
5743: .literalIndex(localVariable.name);
5744: contents[localContentsOffset++] = (byte) (nameIndex >> 8);
5745: contents[localContentsOffset++] = (byte) nameIndex;
5746: descriptorIndex = constantPool
5747: .literalIndex(localVariableTypeBinding
5748: .signature());
5749: contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
5750: contents[localContentsOffset++] = (byte) descriptorIndex;
5751: int resolvedPosition = localVariable.resolvedPosition;
5752: contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
5753: contents[localContentsOffset++] = (byte) resolvedPosition;
5754: }
5755: }
5756: }
5757: int value = numberOfEntries * 10 + 2;
5758: contents[localVariableTableOffset++] = (byte) (value >> 24);
5759: contents[localVariableTableOffset++] = (byte) (value >> 16);
5760: contents[localVariableTableOffset++] = (byte) (value >> 8);
5761: contents[localVariableTableOffset++] = (byte) value;
5762: contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8);
5763: contents[localVariableTableOffset] = (byte) numberOfEntries;
5764: attributeNumber++;
5765:
5766: if (genericLocalVariablesCounter != 0) {
5767: // add the local variable type table attribute
5768: int maxOfEntries = 8 + numberOfGenericEntries * 10;
5769: // reserve enough space
5770: if (localContentsOffset + maxOfEntries >= this .contents.length) {
5771: resizeContents(maxOfEntries);
5772: }
5773: int localVariableTypeNameIndex = constantPool
5774: .literalIndex(AttributeNamesConstants.LocalVariableTypeTableName);
5775: contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8);
5776: contents[localContentsOffset++] = (byte) localVariableTypeNameIndex;
5777: value = numberOfGenericEntries * 10 + 2;
5778: contents[localContentsOffset++] = (byte) (value >> 24);
5779: contents[localContentsOffset++] = (byte) (value >> 16);
5780: contents[localContentsOffset++] = (byte) (value >> 8);
5781: contents[localContentsOffset++] = (byte) value;
5782: contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8);
5783: contents[localContentsOffset++] = (byte) numberOfGenericEntries;
5784:
5785: for (int i = 0; i < genericLocalVariablesCounter; i++) {
5786: LocalVariableBinding localVariable = genericLocalVariables[i];
5787: for (int j = 0; j < localVariable.initializationCount; j++) {
5788: int startPC = localVariable.initializationPCs[j << 1];
5789: int endPC = localVariable.initializationPCs[(j << 1) + 1];
5790: if (startPC != endPC) { // only entries for non zero length
5791: // now we can safely add the local entry
5792: contents[localContentsOffset++] = (byte) (startPC >> 8);
5793: contents[localContentsOffset++] = (byte) startPC;
5794: int length = endPC - startPC;
5795: contents[localContentsOffset++] = (byte) (length >> 8);
5796: contents[localContentsOffset++] = (byte) length;
5797: nameIndex = constantPool
5798: .literalIndex(localVariable.name);
5799: contents[localContentsOffset++] = (byte) (nameIndex >> 8);
5800: contents[localContentsOffset++] = (byte) nameIndex;
5801: descriptorIndex = constantPool
5802: .literalIndex(localVariable.type
5803: .genericTypeSignature());
5804: contents[localContentsOffset++] = (byte) (descriptorIndex >> 8);
5805: contents[localContentsOffset++] = (byte) descriptorIndex;
5806: int resolvedPosition = localVariable.resolvedPosition;
5807: contents[localContentsOffset++] = (byte) (resolvedPosition >> 8);
5808: contents[localContentsOffset++] = (byte) resolvedPosition;
5809: }
5810: }
5811: }
5812: attributeNumber++;
5813: }
5814: }
5815:
5816: if (addStackMaps) {
5817: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
5818: stackMapFrameCodeStream.removeFramePosition(code_length);
5819: if (stackMapFrameCodeStream.hasFramePositions()) {
5820: ArrayList frames = new ArrayList();
5821: traverse(binding, max_locals, this .contents,
5822: codeAttributeOffset + 14, code_length, frames,
5823: false);
5824: int numberOfFrames = frames.size();
5825: if (numberOfFrames > 1) {
5826: int stackMapTableAttributeOffset = localContentsOffset;
5827: // add the stack map table attribute
5828: if (localContentsOffset + 8 >= this .contents.length) {
5829: resizeContents(8);
5830: }
5831: int stackMapTableAttributeNameIndex = constantPool
5832: .literalIndex(AttributeNamesConstants.StackMapTableName);
5833: this .contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8);
5834: this .contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex;
5835:
5836: int stackMapTableAttributeLengthOffset = localContentsOffset;
5837: // generate the attribute
5838: localContentsOffset += 4;
5839: if (localContentsOffset + 4 >= this .contents.length) {
5840: resizeContents(4);
5841: }
5842: int numberOfFramesOffset = localContentsOffset;
5843: localContentsOffset += 2;
5844: if (localContentsOffset + 2 >= this .contents.length) {
5845: resizeContents(2);
5846: }
5847: StackMapFrame currentFrame = (StackMapFrame) frames
5848: .get(0);
5849: StackMapFrame prevFrame = null;
5850: for (int j = 1; j < numberOfFrames; j++) {
5851: // select next frame
5852: prevFrame = currentFrame;
5853: currentFrame = (StackMapFrame) frames.get(j);
5854: // generate current frame
5855: // need to find differences between the current frame and the previous frame
5856: int offsetDelta = currentFrame
5857: .getOffsetDelta(prevFrame);
5858: switch (currentFrame.getFrameType(prevFrame)) {
5859: case StackMapFrame.APPEND_FRAME:
5860: if (localContentsOffset + 3 >= this .contents.length) {
5861: resizeContents(3);
5862: }
5863: int numberOfDifferentLocals = currentFrame
5864: .numberOfDifferentLocals(prevFrame);
5865: this .contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals);
5866: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
5867: this .contents[localContentsOffset++] = (byte) offsetDelta;
5868: int index = currentFrame
5869: .getIndexOfDifferentLocals(numberOfDifferentLocals);
5870: int numberOfLocals = currentFrame
5871: .getNumberOfLocals();
5872: for (int i = index; i < currentFrame.locals.length
5873: && numberOfDifferentLocals > 0; i++) {
5874: if (localContentsOffset + 6 >= this .contents.length) {
5875: resizeContents(6);
5876: }
5877: VerificationTypeInfo info = currentFrame.locals[i];
5878: if (info == null) {
5879: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
5880: } else {
5881: switch (info.id()) {
5882: case T_boolean:
5883: case T_byte:
5884: case T_char:
5885: case T_int:
5886: case T_short:
5887: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
5888: break;
5889: case T_float:
5890: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
5891: break;
5892: case T_long:
5893: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
5894: i++;
5895: break;
5896: case T_double:
5897: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
5898: i++;
5899: break;
5900: case T_null:
5901: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
5902: break;
5903: default:
5904: this .contents[localContentsOffset++] = (byte) info.tag;
5905: switch (info.tag) {
5906: case VerificationTypeInfo.ITEM_UNINITIALIZED:
5907: int offset = info.offset;
5908: this .contents[localContentsOffset++] = (byte) (offset >> 8);
5909: this .contents[localContentsOffset++] = (byte) offset;
5910: break;
5911: case VerificationTypeInfo.ITEM_OBJECT:
5912: int indexForType = constantPool
5913: .literalIndexForType(info
5914: .constantPoolName());
5915: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
5916: this .contents[localContentsOffset++] = (byte) indexForType;
5917: }
5918: }
5919: numberOfDifferentLocals--;
5920: }
5921: }
5922: break;
5923: case StackMapFrame.SAME_FRAME:
5924: if (localContentsOffset + 1 >= this .contents.length) {
5925: resizeContents(1);
5926: }
5927: this .contents[localContentsOffset++] = (byte) offsetDelta;
5928: break;
5929: case StackMapFrame.SAME_FRAME_EXTENDED:
5930: if (localContentsOffset + 3 >= this .contents.length) {
5931: resizeContents(3);
5932: }
5933: this .contents[localContentsOffset++] = (byte) 251;
5934: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
5935: this .contents[localContentsOffset++] = (byte) offsetDelta;
5936: break;
5937: case StackMapFrame.CHOP_FRAME:
5938: if (localContentsOffset + 3 >= this .contents.length) {
5939: resizeContents(3);
5940: }
5941: numberOfDifferentLocals = -currentFrame
5942: .numberOfDifferentLocals(prevFrame);
5943: this .contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals);
5944: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
5945: this .contents[localContentsOffset++] = (byte) offsetDelta;
5946: break;
5947: case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS:
5948: if (localContentsOffset + 4 >= this .contents.length) {
5949: resizeContents(4);
5950: }
5951: this .contents[localContentsOffset++] = (byte) (offsetDelta + 64);
5952: if (currentFrame.stackItems[0] == null) {
5953: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
5954: } else {
5955: switch (currentFrame.stackItems[0].id()) {
5956: case T_boolean:
5957: case T_byte:
5958: case T_char:
5959: case T_int:
5960: case T_short:
5961: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
5962: break;
5963: case T_float:
5964: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
5965: break;
5966: case T_long:
5967: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
5968: break;
5969: case T_double:
5970: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
5971: break;
5972: case T_null:
5973: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
5974: break;
5975: default:
5976: VerificationTypeInfo info = currentFrame.stackItems[0];
5977: byte tag = (byte) info.tag;
5978: this .contents[localContentsOffset++] = tag;
5979: switch (tag) {
5980: case VerificationTypeInfo.ITEM_UNINITIALIZED:
5981: int offset = info.offset;
5982: this .contents[localContentsOffset++] = (byte) (offset >> 8);
5983: this .contents[localContentsOffset++] = (byte) offset;
5984: break;
5985: case VerificationTypeInfo.ITEM_OBJECT:
5986: int indexForType = constantPool
5987: .literalIndexForType(info
5988: .constantPoolName());
5989: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
5990: this .contents[localContentsOffset++] = (byte) indexForType;
5991: }
5992: }
5993: }
5994: break;
5995: case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED:
5996: if (localContentsOffset + 6 >= this .contents.length) {
5997: resizeContents(6);
5998: }
5999: this .contents[localContentsOffset++] = (byte) 247;
6000: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
6001: this .contents[localContentsOffset++] = (byte) offsetDelta;
6002: if (currentFrame.stackItems[0] == null) {
6003: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
6004: } else {
6005: switch (currentFrame.stackItems[0].id()) {
6006: case T_boolean:
6007: case T_byte:
6008: case T_char:
6009: case T_int:
6010: case T_short:
6011: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
6012: break;
6013: case T_float:
6014: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
6015: break;
6016: case T_long:
6017: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
6018: break;
6019: case T_double:
6020: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
6021: break;
6022: case T_null:
6023: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
6024: break;
6025: default:
6026: VerificationTypeInfo info = currentFrame.stackItems[0];
6027: byte tag = (byte) info.tag;
6028: this .contents[localContentsOffset++] = tag;
6029: switch (tag) {
6030: case VerificationTypeInfo.ITEM_UNINITIALIZED:
6031: int offset = info.offset;
6032: this .contents[localContentsOffset++] = (byte) (offset >> 8);
6033: this .contents[localContentsOffset++] = (byte) offset;
6034: break;
6035: case VerificationTypeInfo.ITEM_OBJECT:
6036: int indexForType = constantPool
6037: .literalIndexForType(info
6038: .constantPoolName());
6039: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
6040: this .contents[localContentsOffset++] = (byte) indexForType;
6041: }
6042: }
6043: }
6044: break;
6045: default:
6046: // FULL_FRAME
6047: if (localContentsOffset + 5 >= this .contents.length) {
6048: resizeContents(5);
6049: }
6050: this .contents[localContentsOffset++] = (byte) 255;
6051: this .contents[localContentsOffset++] = (byte) (offsetDelta >> 8);
6052: this .contents[localContentsOffset++] = (byte) offsetDelta;
6053: int numberOfLocalOffset = localContentsOffset;
6054: localContentsOffset += 2; // leave two spots for number of locals
6055: int numberOfLocalEntries = 0;
6056: numberOfLocals = currentFrame
6057: .getNumberOfLocals();
6058: int numberOfEntries = 0;
6059: int localsLength = currentFrame.locals == null ? 0
6060: : currentFrame.locals.length;
6061: for (int i = 0; i < localsLength
6062: && numberOfLocalEntries < numberOfLocals; i++) {
6063: if (localContentsOffset + 3 >= this .contents.length) {
6064: resizeContents(3);
6065: }
6066: VerificationTypeInfo info = currentFrame.locals[i];
6067: if (info == null) {
6068: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
6069: } else {
6070: switch (info.id()) {
6071: case T_boolean:
6072: case T_byte:
6073: case T_char:
6074: case T_int:
6075: case T_short:
6076: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
6077: break;
6078: case T_float:
6079: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
6080: break;
6081: case T_long:
6082: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
6083: i++;
6084: break;
6085: case T_double:
6086: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
6087: i++;
6088: break;
6089: case T_null:
6090: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
6091: break;
6092: default:
6093: this .contents[localContentsOffset++] = (byte) info.tag;
6094: switch (info.tag) {
6095: case VerificationTypeInfo.ITEM_UNINITIALIZED:
6096: int offset = info.offset;
6097: this .contents[localContentsOffset++] = (byte) (offset >> 8);
6098: this .contents[localContentsOffset++] = (byte) offset;
6099: break;
6100: case VerificationTypeInfo.ITEM_OBJECT:
6101: int indexForType = constantPool
6102: .literalIndexForType(info
6103: .constantPoolName());
6104: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
6105: this .contents[localContentsOffset++] = (byte) indexForType;
6106: }
6107: }
6108: numberOfLocalEntries++;
6109: }
6110: numberOfEntries++;
6111: }
6112: if (localContentsOffset + 4 >= this .contents.length) {
6113: resizeContents(4);
6114: }
6115: this .contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
6116: this .contents[numberOfLocalOffset] = (byte) numberOfEntries;
6117: int numberOfStackItems = currentFrame.numberOfStackItems;
6118: this .contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
6119: this .contents[localContentsOffset++] = (byte) numberOfStackItems;
6120: for (int i = 0; i < numberOfStackItems; i++) {
6121: if (localContentsOffset + 3 >= this .contents.length) {
6122: resizeContents(3);
6123: }
6124: VerificationTypeInfo info = currentFrame.stackItems[i];
6125: if (info == null) {
6126: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
6127: } else {
6128: switch (info.id()) {
6129: case T_boolean:
6130: case T_byte:
6131: case T_char:
6132: case T_int:
6133: case T_short:
6134: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
6135: break;
6136: case T_float:
6137: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
6138: break;
6139: case T_long:
6140: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
6141: break;
6142: case T_double:
6143: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
6144: break;
6145: case T_null:
6146: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
6147: break;
6148: default:
6149: this .contents[localContentsOffset++] = (byte) info.tag;
6150: switch (info.tag) {
6151: case VerificationTypeInfo.ITEM_UNINITIALIZED:
6152: int offset = info.offset;
6153: this .contents[localContentsOffset++] = (byte) (offset >> 8);
6154: this .contents[localContentsOffset++] = (byte) offset;
6155: break;
6156: case VerificationTypeInfo.ITEM_OBJECT:
6157: int indexForType = constantPool
6158: .literalIndexForType(info
6159: .constantPoolName());
6160: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
6161: this .contents[localContentsOffset++] = (byte) indexForType;
6162: }
6163: }
6164: }
6165: }
6166: }
6167: }
6168:
6169: numberOfFrames--;
6170: if (numberOfFrames != 0) {
6171: this .contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
6172: this .contents[numberOfFramesOffset] = (byte) numberOfFrames;
6173:
6174: int attributeLength = localContentsOffset
6175: - stackMapTableAttributeLengthOffset
6176: - 4;
6177: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24);
6178: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16);
6179: this .contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8);
6180: this .contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength;
6181: attributeNumber++;
6182: } else {
6183: localContentsOffset = stackMapTableAttributeOffset;
6184: }
6185: }
6186: }
6187: }
6188:
6189: if ((this .produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) {
6190: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
6191: stackMapFrameCodeStream.removeFramePosition(code_length);
6192: if (stackMapFrameCodeStream.hasFramePositions()) {
6193: ArrayList frames = new ArrayList();
6194: traverse(this .codeStream.methodDeclaration.binding,
6195: max_locals, this .contents,
6196: codeAttributeOffset + 14, code_length, frames,
6197: false);
6198: int numberOfFrames = frames.size();
6199: if (numberOfFrames > 1) {
6200: int stackMapTableAttributeOffset = localContentsOffset;
6201: // add the stack map table attribute
6202: if (localContentsOffset + 8 >= this .contents.length) {
6203: resizeContents(8);
6204: }
6205: int stackMapAttributeNameIndex = constantPool
6206: .literalIndex(AttributeNamesConstants.StackMapName);
6207: this .contents[localContentsOffset++] = (byte) (stackMapAttributeNameIndex >> 8);
6208: this .contents[localContentsOffset++] = (byte) stackMapAttributeNameIndex;
6209:
6210: int stackMapAttributeLengthOffset = localContentsOffset;
6211: // generate the attribute
6212: localContentsOffset += 4;
6213: if (localContentsOffset + 4 >= this .contents.length) {
6214: resizeContents(4);
6215: }
6216: int numberOfFramesOffset = localContentsOffset;
6217: localContentsOffset += 2;
6218: if (localContentsOffset + 2 >= this .contents.length) {
6219: resizeContents(2);
6220: }
6221: StackMapFrame currentFrame = (StackMapFrame) frames
6222: .get(0);
6223: for (int j = 1; j < numberOfFrames; j++) {
6224: // select next frame
6225: currentFrame = (StackMapFrame) frames.get(j);
6226: // generate current frame
6227: // need to find differences between the current frame and the previous frame
6228: int frameOffset = currentFrame.pc;
6229: // FULL_FRAME
6230: if (localContentsOffset + 5 >= this .contents.length) {
6231: resizeContents(5);
6232: }
6233: this .contents[localContentsOffset++] = (byte) (frameOffset >> 8);
6234: this .contents[localContentsOffset++] = (byte) frameOffset;
6235: int numberOfLocalOffset = localContentsOffset;
6236: localContentsOffset += 2; // leave two spots for number of locals
6237: int numberOfLocalEntries = 0;
6238: int numberOfLocals = currentFrame
6239: .getNumberOfLocals();
6240: int numberOfEntries = 0;
6241: int localsLength = currentFrame.locals == null ? 0
6242: : currentFrame.locals.length;
6243: for (int i = 0; i < localsLength
6244: && numberOfLocalEntries < numberOfLocals; i++) {
6245: if (localContentsOffset + 3 >= this .contents.length) {
6246: resizeContents(3);
6247: }
6248: VerificationTypeInfo info = currentFrame.locals[i];
6249: if (info == null) {
6250: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
6251: } else {
6252: switch (info.id()) {
6253: case T_boolean:
6254: case T_byte:
6255: case T_char:
6256: case T_int:
6257: case T_short:
6258: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
6259: break;
6260: case T_float:
6261: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
6262: break;
6263: case T_long:
6264: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
6265: i++;
6266: break;
6267: case T_double:
6268: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
6269: i++;
6270: break;
6271: case T_null:
6272: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
6273: break;
6274: default:
6275: this .contents[localContentsOffset++] = (byte) info.tag;
6276: switch (info.tag) {
6277: case VerificationTypeInfo.ITEM_UNINITIALIZED:
6278: int offset = info.offset;
6279: this .contents[localContentsOffset++] = (byte) (offset >> 8);
6280: this .contents[localContentsOffset++] = (byte) offset;
6281: break;
6282: case VerificationTypeInfo.ITEM_OBJECT:
6283: int indexForType = constantPool
6284: .literalIndexForType(info
6285: .constantPoolName());
6286: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
6287: this .contents[localContentsOffset++] = (byte) indexForType;
6288: }
6289: }
6290: numberOfLocalEntries++;
6291: }
6292: numberOfEntries++;
6293: }
6294: if (localContentsOffset + 4 >= this .contents.length) {
6295: resizeContents(4);
6296: }
6297: this .contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8);
6298: this .contents[numberOfLocalOffset] = (byte) numberOfEntries;
6299: int numberOfStackItems = currentFrame.numberOfStackItems;
6300: this .contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8);
6301: this .contents[localContentsOffset++] = (byte) numberOfStackItems;
6302: for (int i = 0; i < numberOfStackItems; i++) {
6303: if (localContentsOffset + 3 >= this .contents.length) {
6304: resizeContents(3);
6305: }
6306: VerificationTypeInfo info = currentFrame.stackItems[i];
6307: if (info == null) {
6308: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP;
6309: } else {
6310: switch (info.id()) {
6311: case T_boolean:
6312: case T_byte:
6313: case T_char:
6314: case T_int:
6315: case T_short:
6316: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER;
6317: break;
6318: case T_float:
6319: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT;
6320: break;
6321: case T_long:
6322: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG;
6323: break;
6324: case T_double:
6325: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE;
6326: break;
6327: case T_null:
6328: this .contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL;
6329: break;
6330: default:
6331: this .contents[localContentsOffset++] = (byte) info.tag;
6332: switch (info.tag) {
6333: case VerificationTypeInfo.ITEM_UNINITIALIZED:
6334: int offset = info.offset;
6335: this .contents[localContentsOffset++] = (byte) (offset >> 8);
6336: this .contents[localContentsOffset++] = (byte) offset;
6337: break;
6338: case VerificationTypeInfo.ITEM_OBJECT:
6339: int indexForType = constantPool
6340: .literalIndexForType(info
6341: .constantPoolName());
6342: this .contents[localContentsOffset++] = (byte) (indexForType >> 8);
6343: this .contents[localContentsOffset++] = (byte) indexForType;
6344: }
6345: }
6346: }
6347: }
6348: }
6349:
6350: numberOfFrames--;
6351: if (numberOfFrames != 0) {
6352: this .contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8);
6353: this .contents[numberOfFramesOffset] = (byte) numberOfFrames;
6354:
6355: int attributeLength = localContentsOffset
6356: - stackMapAttributeLengthOffset - 4;
6357: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 24);
6358: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 16);
6359: this .contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 8);
6360: this .contents[stackMapAttributeLengthOffset] = (byte) attributeLength;
6361: attributeNumber++;
6362: } else {
6363: localContentsOffset = stackMapTableAttributeOffset;
6364: }
6365: }
6366: }
6367: }
6368:
6369: // update the number of attributes
6370: // ensure first that there is enough space available inside the contents array
6371: if (codeAttributeAttributeOffset + 2 >= this .contents.length) {
6372: resizeContents(2);
6373: }
6374: contents[codeAttributeAttributeOffset++] = (byte) (attributeNumber >> 8);
6375: contents[codeAttributeAttributeOffset] = (byte) attributeNumber;
6376:
6377: // update the attribute length
6378: int codeAttributeLength = localContentsOffset
6379: - (codeAttributeOffset + 6);
6380: contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24);
6381: contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16);
6382: contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8);
6383: contents[codeAttributeOffset + 5] = (byte) codeAttributeLength;
6384: contentsOffset = localContentsOffset;
6385: }
6386:
6387: /**
6388: * INTERNAL USE-ONLY
6389: * That method completes the creation of the code attribute by setting
6390: * - the attribute_length
6391: * - max_stack
6392: * - max_locals
6393: * - code_length
6394: * - exception table
6395: * - and debug attributes if necessary.
6396: *
6397: * @param binding org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding
6398: * @param codeAttributeOffset <CODE>int</CODE>
6399: */
6400: public void completeCodeAttributeForSyntheticMethod(
6401: SyntheticMethodBinding binding, int codeAttributeOffset,
6402: int[] startLineIndexes) {
6403:
6404: this .completeCodeAttributeForSyntheticMethod(false, binding,
6405: codeAttributeOffset, startLineIndexes);
6406: }
6407:
6408: /**
6409: * INTERNAL USE-ONLY
6410: * Complete the creation of a method info by setting up the number of attributes at the right offset.
6411: *
6412: * @param methodAttributeOffset <CODE>int</CODE>
6413: * @param attributeNumber <CODE>int</CODE>
6414: */
6415: public void completeMethodInfo(int methodAttributeOffset,
6416: int attributeNumber) {
6417: // update the number of attributes
6418: contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8);
6419: contents[methodAttributeOffset] = (byte) attributeNumber;
6420: }
6421:
6422: /**
6423: * INTERNAL USE-ONLY
6424: * This methods returns a char[] representing the file name of the receiver
6425: *
6426: * @return char[]
6427: */
6428: public char[] fileName() {
6429: return constantPool.UTF8Cache.returnKeyFor(2);
6430: }
6431:
6432: private void generateAnnotation(Annotation annotation,
6433: int attributeOffset) {
6434: if (contentsOffset + 4 >= this .contents.length) {
6435: resizeContents(4);
6436: }
6437: TypeBinding annotationTypeBinding = annotation.resolvedType;
6438: if (annotationTypeBinding == null) {
6439: this .contentsOffset = attributeOffset;
6440: return;
6441: }
6442: final int typeIndex = constantPool
6443: .literalIndex(annotationTypeBinding.signature());
6444: contents[contentsOffset++] = (byte) (typeIndex >> 8);
6445: contents[contentsOffset++] = (byte) typeIndex;
6446: if (annotation instanceof NormalAnnotation) {
6447: NormalAnnotation normalAnnotation = (NormalAnnotation) annotation;
6448: MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs;
6449: if (memberValuePairs != null) {
6450: final int memberValuePairsLength = memberValuePairs.length;
6451: contents[contentsOffset++] = (byte) (memberValuePairsLength >> 8);
6452: contents[contentsOffset++] = (byte) memberValuePairsLength;
6453: for (int i = 0; i < memberValuePairsLength; i++) {
6454: MemberValuePair memberValuePair = memberValuePairs[i];
6455: if (contentsOffset + 2 >= this .contents.length) {
6456: resizeContents(2);
6457: }
6458: final int elementNameIndex = constantPool
6459: .literalIndex(memberValuePair.name);
6460: contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
6461: contents[contentsOffset++] = (byte) elementNameIndex;
6462: MethodBinding methodBinding = memberValuePair.binding;
6463: if (methodBinding == null) {
6464: contentsOffset = attributeOffset;
6465: } else {
6466: generateElementValue(memberValuePair.value,
6467: methodBinding.returnType,
6468: attributeOffset);
6469: }
6470: }
6471: } else {
6472: contents[contentsOffset++] = 0;
6473: contents[contentsOffset++] = 0;
6474: }
6475: } else if (annotation instanceof SingleMemberAnnotation) {
6476: SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
6477: // this is a single member annotation (one member value)
6478: contents[contentsOffset++] = 0;
6479: contents[contentsOffset++] = 1;
6480: if (contentsOffset + 2 >= this .contents.length) {
6481: resizeContents(2);
6482: }
6483: final int elementNameIndex = constantPool
6484: .literalIndex(VALUE);
6485: contents[contentsOffset++] = (byte) (elementNameIndex >> 8);
6486: contents[contentsOffset++] = (byte) elementNameIndex;
6487: MethodBinding methodBinding = singleMemberAnnotation
6488: .memberValuePairs()[0].binding;
6489: if (methodBinding == null) {
6490: contentsOffset = attributeOffset;
6491: } else {
6492: generateElementValue(
6493: singleMemberAnnotation.memberValue,
6494: methodBinding.returnType, attributeOffset);
6495: }
6496: } else {
6497: // this is a marker annotation (no member value pairs)
6498: contents[contentsOffset++] = 0;
6499: contents[contentsOffset++] = 0;
6500: }
6501: }
6502:
6503: /**
6504: * INTERNAL USE-ONLY
6505: * That method generates the header of a code attribute.
6506: * - the index inside the constant pool for the attribute name ("Code")
6507: * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4).
6508: */
6509: public void generateCodeAttributeHeader() {
6510: if (contentsOffset + 20 >= this .contents.length) {
6511: resizeContents(20);
6512: }
6513: int constantValueNameIndex = constantPool
6514: .literalIndex(AttributeNamesConstants.CodeName);
6515: contents[contentsOffset++] = (byte) (constantValueNameIndex >> 8);
6516: contents[contentsOffset++] = (byte) constantValueNameIndex;
6517: // leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4)
6518: contentsOffset += 12;
6519: }
6520:
6521: private void generateElementValue(Expression defaultValue,
6522: TypeBinding memberValuePairReturnType, int attributeOffset) {
6523: Constant constant = defaultValue.constant;
6524: TypeBinding defaultValueBinding = defaultValue.resolvedType;
6525: if (defaultValueBinding == null) {
6526: contentsOffset = attributeOffset;
6527: } else {
6528: if (memberValuePairReturnType.isArrayType()
6529: && !defaultValueBinding.isArrayType()) {
6530: // automatic wrapping
6531: if (contentsOffset + 3 >= this .contents.length) {
6532: resizeContents(3);
6533: }
6534: contents[contentsOffset++] = (byte) '[';
6535: contents[contentsOffset++] = (byte) 0;
6536: contents[contentsOffset++] = (byte) 1;
6537: }
6538: if (constant != null && constant != Constant.NotAConstant) {
6539: generateElementValue(attributeOffset, defaultValue,
6540: constant, memberValuePairReturnType
6541: .leafComponentType());
6542: } else {
6543: generateElementValueForNonConstantExpression(
6544: defaultValue, attributeOffset,
6545: defaultValueBinding);
6546: }
6547: }
6548: }
6549:
6550: /**
6551: * @param attributeOffset
6552: */
6553: private void generateElementValue(int attributeOffset,
6554: Expression defaultValue, Constant constant,
6555: TypeBinding binding) {
6556: if (contentsOffset + 3 >= this .contents.length) {
6557: resizeContents(3);
6558: }
6559: switch (binding.id) {
6560: case T_boolean:
6561: contents[contentsOffset++] = (byte) 'Z';
6562: int booleanValueIndex = constantPool.literalIndex(constant
6563: .booleanValue() ? 1 : 0);
6564: contents[contentsOffset++] = (byte) (booleanValueIndex >> 8);
6565: contents[contentsOffset++] = (byte) booleanValueIndex;
6566: break;
6567: case T_byte:
6568: contents[contentsOffset++] = (byte) 'B';
6569: int integerValueIndex = constantPool.literalIndex(constant
6570: .intValue());
6571: contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
6572: contents[contentsOffset++] = (byte) integerValueIndex;
6573: break;
6574: case T_char:
6575: contents[contentsOffset++] = (byte) 'C';
6576: integerValueIndex = constantPool.literalIndex(constant
6577: .intValue());
6578: contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
6579: contents[contentsOffset++] = (byte) integerValueIndex;
6580: break;
6581: case T_int:
6582: contents[contentsOffset++] = (byte) 'I';
6583: integerValueIndex = constantPool.literalIndex(constant
6584: .intValue());
6585: contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
6586: contents[contentsOffset++] = (byte) integerValueIndex;
6587: break;
6588: case T_short:
6589: contents[contentsOffset++] = (byte) 'S';
6590: integerValueIndex = constantPool.literalIndex(constant
6591: .intValue());
6592: contents[contentsOffset++] = (byte) (integerValueIndex >> 8);
6593: contents[contentsOffset++] = (byte) integerValueIndex;
6594: break;
6595: case T_float:
6596: contents[contentsOffset++] = (byte) 'F';
6597: int floatValueIndex = constantPool.literalIndex(constant
6598: .floatValue());
6599: contents[contentsOffset++] = (byte) (floatValueIndex >> 8);
6600: contents[contentsOffset++] = (byte) floatValueIndex;
6601: break;
6602: case T_double:
6603: contents[contentsOffset++] = (byte) 'D';
6604: int doubleValueIndex = constantPool.literalIndex(constant
6605: .doubleValue());
6606: contents[contentsOffset++] = (byte) (doubleValueIndex >> 8);
6607: contents[contentsOffset++] = (byte) doubleValueIndex;
6608: break;
6609: case T_long:
6610: contents[contentsOffset++] = (byte) 'J';
6611: int longValueIndex = constantPool.literalIndex(constant
6612: .longValue());
6613: contents[contentsOffset++] = (byte) (longValueIndex >> 8);
6614: contents[contentsOffset++] = (byte) longValueIndex;
6615: break;
6616: case T_JavaLangString:
6617: contents[contentsOffset++] = (byte) 's';
6618: int stringValueIndex = constantPool
6619: .literalIndex(((StringConstant) constant)
6620: .stringValue().toCharArray());
6621: if (stringValueIndex == -1) {
6622: if (!creatingProblemType) {
6623: // report an error and abort: will lead to a problem type classfile creation
6624: TypeDeclaration typeDeclaration = referenceBinding.scope.referenceContext;
6625: typeDeclaration.scope.problemReporter()
6626: .stringConstantIsExceedingUtf8Limit(
6627: defaultValue);
6628: } else {
6629: // already inside a problem type creation : no attribute
6630: contentsOffset = attributeOffset;
6631: }
6632: } else {
6633: contents[contentsOffset++] = (byte) (stringValueIndex >> 8);
6634: contents[contentsOffset++] = (byte) stringValueIndex;
6635: }
6636: }
6637: }
6638:
6639: private void generateElementValueForNonConstantExpression(
6640: Expression defaultValue, int attributeOffset,
6641: TypeBinding defaultValueBinding) {
6642: if (defaultValueBinding != null) {
6643: if (defaultValueBinding.isEnum()) {
6644: if (contentsOffset + 5 >= this .contents.length) {
6645: resizeContents(5);
6646: }
6647: contents[contentsOffset++] = (byte) 'e';
6648: FieldBinding fieldBinding = null;
6649: if (defaultValue instanceof QualifiedNameReference) {
6650: QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue;
6651: fieldBinding = (FieldBinding) nameReference.binding;
6652: } else if (defaultValue instanceof SingleNameReference) {
6653: SingleNameReference nameReference = (SingleNameReference) defaultValue;
6654: fieldBinding = (FieldBinding) nameReference.binding;
6655: } else {
6656: contentsOffset = attributeOffset;
6657: }
6658: if (fieldBinding != null) {
6659: final int enumConstantTypeNameIndex = constantPool
6660: .literalIndex(fieldBinding.type.signature());
6661: final int enumConstantNameIndex = constantPool
6662: .literalIndex(fieldBinding.name);
6663: contents[contentsOffset++] = (byte) (enumConstantTypeNameIndex >> 8);
6664: contents[contentsOffset++] = (byte) enumConstantTypeNameIndex;
6665: contents[contentsOffset++] = (byte) (enumConstantNameIndex >> 8);
6666: contents[contentsOffset++] = (byte) enumConstantNameIndex;
6667: }
6668: } else if (defaultValueBinding.isAnnotationType()) {
6669: if (contentsOffset + 1 >= this .contents.length) {
6670: resizeContents(1);
6671: }
6672: contents[contentsOffset++] = (byte) '@';
6673: generateAnnotation((Annotation) defaultValue,
6674: attributeOffset);
6675: } else if (defaultValueBinding.isArrayType()) {
6676: // array type
6677: if (contentsOffset + 3 >= this .contents.length) {
6678: resizeContents(3);
6679: }
6680: contents[contentsOffset++] = (byte) '[';
6681: if (defaultValue instanceof ArrayInitializer) {
6682: ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue;
6683: int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length
6684: : 0;
6685: contents[contentsOffset++] = (byte) (arrayLength >> 8);
6686: contents[contentsOffset++] = (byte) arrayLength;
6687: for (int i = 0; i < arrayLength; i++) {
6688: generateElementValue(
6689: arrayInitializer.expressions[i],
6690: defaultValueBinding.leafComponentType(),
6691: attributeOffset);
6692: }
6693: } else {
6694: contentsOffset = attributeOffset;
6695: }
6696: } else {
6697: // class type
6698: if (contentsOffset + 3 >= this .contents.length) {
6699: resizeContents(3);
6700: }
6701: contents[contentsOffset++] = (byte) 'c';
6702: if (defaultValue instanceof ClassLiteralAccess) {
6703: ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess) defaultValue;
6704: final int classInfoIndex = constantPool
6705: .literalIndex(classLiteralAccess.targetType
6706: .signature());
6707: contents[contentsOffset++] = (byte) (classInfoIndex >> 8);
6708: contents[contentsOffset++] = (byte) classInfoIndex;
6709: } else {
6710: contentsOffset = attributeOffset;
6711: }
6712: }
6713: } else {
6714: contentsOffset = attributeOffset;
6715: }
6716: }
6717:
6718: public int generateMethodInfoAttribute(MethodBinding methodBinding) {
6719: return generateMethodInfoAttribute(methodBinding, false);
6720: }
6721:
6722: public int generateMethodInfoAttribute(MethodBinding methodBinding,
6723: AnnotationMethodDeclaration declaration) {
6724: int attributesNumber = generateMethodInfoAttribute(methodBinding);
6725: int attributeOffset = contentsOffset;
6726: if ((declaration.modifiers & ClassFileConstants.AccAnnotationDefault) != 0) {
6727: // add an annotation default attribute
6728: int annotationDefaultNameIndex = constantPool
6729: .literalIndex(AttributeNamesConstants.AnnotationDefaultName);
6730: contents[contentsOffset++] = (byte) (annotationDefaultNameIndex >> 8);
6731: contents[contentsOffset++] = (byte) annotationDefaultNameIndex;
6732: int attributeLengthOffset = contentsOffset;
6733: contentsOffset += 4;
6734: if (contentsOffset + 4 >= this .contents.length) {
6735: resizeContents(4);
6736: }
6737: generateElementValue(declaration.defaultValue,
6738: declaration.binding.returnType, attributeOffset);
6739: if (contentsOffset != attributeOffset) {
6740: int attributeLength = contentsOffset
6741: - attributeLengthOffset - 4;
6742: contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
6743: contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
6744: contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
6745: contents[attributeLengthOffset++] = (byte) attributeLength;
6746: attributesNumber++;
6747: }
6748: }
6749: return attributesNumber;
6750: }
6751:
6752: /**
6753: * INTERNAL USE-ONLY
6754: * That method generates the attributes of a code attribute.
6755: * They could be:
6756: * - an exception attribute for each try/catch found inside the method
6757: * - a deprecated attribute
6758: * - a synthetic attribute for synthetic access methods
6759: *
6760: * It returns the number of attributes created for the code attribute.
6761: *
6762: * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
6763: * @return <CODE>int</CODE>
6764: */
6765: public int generateMethodInfoAttribute(MethodBinding methodBinding,
6766: boolean createProblemMethod) {
6767: // leave two bytes for the attribute_number
6768: contentsOffset += 2;
6769: if (contentsOffset + 2 >= this .contents.length) {
6770: resizeContents(2);
6771: }
6772: // now we can handle all the attribute for that method info:
6773: // it could be:
6774: // - a CodeAttribute
6775: // - a ExceptionAttribute
6776: // - a DeprecatedAttribute
6777: // - a SyntheticAttribute
6778:
6779: // Exception attribute
6780: ReferenceBinding[] thrownsExceptions;
6781: int attributeNumber = 0;
6782: if ((thrownsExceptions = methodBinding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
6783: // The method has a throw clause. So we need to add an exception attribute
6784: // check that there is enough space to write all the bytes for the exception attribute
6785: int length = thrownsExceptions.length;
6786: int exSize = 8 + length * 2;
6787: if (exSize + contentsOffset >= this .contents.length) {
6788: resizeContents(exSize);
6789: }
6790: int exceptionNameIndex = constantPool
6791: .literalIndex(AttributeNamesConstants.ExceptionsName);
6792: contents[contentsOffset++] = (byte) (exceptionNameIndex >> 8);
6793: contents[contentsOffset++] = (byte) exceptionNameIndex;
6794: // The attribute length = length * 2 + 2 in case of a exception attribute
6795: int attributeLength = length * 2 + 2;
6796: contents[contentsOffset++] = (byte) (attributeLength >> 24);
6797: contents[contentsOffset++] = (byte) (attributeLength >> 16);
6798: contents[contentsOffset++] = (byte) (attributeLength >> 8);
6799: contents[contentsOffset++] = (byte) attributeLength;
6800: contents[contentsOffset++] = (byte) (length >> 8);
6801: contents[contentsOffset++] = (byte) length;
6802: for (int i = 0; i < length; i++) {
6803: int exceptionIndex = constantPool
6804: .literalIndexForType(thrownsExceptions[i]);
6805: contents[contentsOffset++] = (byte) (exceptionIndex >> 8);
6806: contents[contentsOffset++] = (byte) exceptionIndex;
6807: }
6808: attributeNumber++;
6809: }
6810: if (methodBinding.isDeprecated()) {
6811: // Deprecated attribute
6812: // Check that there is enough space to write the deprecated attribute
6813: if (contentsOffset + 6 >= this .contents.length) {
6814: resizeContents(6);
6815: }
6816: int deprecatedAttributeNameIndex = constantPool
6817: .literalIndex(AttributeNamesConstants.DeprecatedName);
6818: contents[contentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8);
6819: contents[contentsOffset++] = (byte) deprecatedAttributeNameIndex;
6820: // the length of a deprecated attribute is equals to 0
6821: contents[contentsOffset++] = 0;
6822: contents[contentsOffset++] = 0;
6823: contents[contentsOffset++] = 0;
6824: contents[contentsOffset++] = 0;
6825:
6826: attributeNumber++;
6827: }
6828: if (this .targetJDK < ClassFileConstants.JDK1_5) {
6829: if (methodBinding.isSynthetic()) {
6830: // Synthetic attribute
6831: // Check that there is enough space to write the deprecated attribute
6832: if (contentsOffset + 6 >= this .contents.length) {
6833: resizeContents(6);
6834: }
6835: int syntheticAttributeNameIndex = constantPool
6836: .literalIndex(AttributeNamesConstants.SyntheticName);
6837: contents[contentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8);
6838: contents[contentsOffset++] = (byte) syntheticAttributeNameIndex;
6839: // the length of a synthetic attribute is equals to 0
6840: contents[contentsOffset++] = 0;
6841: contents[contentsOffset++] = 0;
6842: contents[contentsOffset++] = 0;
6843: contents[contentsOffset++] = 0;
6844:
6845: attributeNumber++;
6846: }
6847: if (methodBinding.isVarargs()) {
6848: /*
6849: * handle of the target jsr14 for varargs in the source
6850: * Varargs attribute
6851: * Check that there is enough space to write the deprecated attribute
6852: */
6853: if (contentsOffset + 6 >= this .contents.length) {
6854: resizeContents(6);
6855: }
6856: int varargsAttributeNameIndex = constantPool
6857: .literalIndex(AttributeNamesConstants.VarargsName);
6858: contents[contentsOffset++] = (byte) (varargsAttributeNameIndex >> 8);
6859: contents[contentsOffset++] = (byte) varargsAttributeNameIndex;
6860: // the length of a varargs attribute is equals to 0
6861: contents[contentsOffset++] = 0;
6862: contents[contentsOffset++] = 0;
6863: contents[contentsOffset++] = 0;
6864: contents[contentsOffset++] = 0;
6865:
6866: attributeNumber++;
6867: }
6868: }
6869: // add signature attribute
6870: char[] genericSignature = methodBinding.genericSignature();
6871: if (genericSignature != null) {
6872: // check that there is enough space to write all the bytes for the field info corresponding
6873: // to the @fieldBinding
6874: if (contentsOffset + 8 >= this .contents.length) {
6875: resizeContents(8);
6876: }
6877: int signatureAttributeNameIndex = constantPool
6878: .literalIndex(AttributeNamesConstants.SignatureName);
6879: contents[contentsOffset++] = (byte) (signatureAttributeNameIndex >> 8);
6880: contents[contentsOffset++] = (byte) signatureAttributeNameIndex;
6881: // the length of a signature attribute is equals to 2
6882: contents[contentsOffset++] = 0;
6883: contents[contentsOffset++] = 0;
6884: contents[contentsOffset++] = 0;
6885: contents[contentsOffset++] = 2;
6886: int signatureIndex = constantPool
6887: .literalIndex(genericSignature);
6888: contents[contentsOffset++] = (byte) (signatureIndex >> 8);
6889: contents[contentsOffset++] = (byte) signatureIndex;
6890: attributeNumber++;
6891: }
6892: if (this .targetJDK >= ClassFileConstants.JDK1_5
6893: && !this .creatingProblemType && !createProblemMethod) {
6894: AbstractMethodDeclaration methodDeclaration = methodBinding
6895: .sourceMethod();
6896: if (methodDeclaration != null) {
6897: Annotation[] annotations = methodDeclaration.annotations;
6898: if (annotations != null) {
6899: attributeNumber += generateRuntimeAnnotations(annotations);
6900: }
6901: if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) {
6902: Argument[] arguments = methodDeclaration.arguments;
6903: if (arguments != null) {
6904: attributeNumber += generateRuntimeAnnotationsForParameters(arguments);
6905: }
6906: }
6907: }
6908: }
6909: return attributeNumber;
6910: }
6911:
6912: /**
6913: * INTERNAL USE-ONLY
6914: * That method generates the header of a method info:
6915: * The header consists in:
6916: * - the access flags
6917: * - the name index of the method name inside the constant pool
6918: * - the descriptor index of the signature of the method inside the constant pool.
6919: *
6920: * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
6921: */
6922: public void generateMethodInfoHeader(MethodBinding methodBinding) {
6923: generateMethodInfoHeader(methodBinding, methodBinding.modifiers);
6924: }
6925:
6926: /**
6927: * INTERNAL USE-ONLY
6928: * That method generates the header of a method info:
6929: * The header consists in:
6930: * - the access flags
6931: * - the name index of the method name inside the constant pool
6932: * - the descriptor index of the signature of the method inside the constant pool.
6933: *
6934: * @param methodBinding org.eclipse.jdt.internal.compiler.lookup.MethodBinding
6935: * @param accessFlags the access flags
6936: */
6937: public void generateMethodInfoHeader(MethodBinding methodBinding,
6938: int accessFlags) {
6939: // check that there is enough space to write all the bytes for the method info corresponding
6940: // to the @methodBinding
6941: methodCount++; // add one more method
6942: if (contentsOffset + 10 >= this .contents.length) {
6943: resizeContents(10);
6944: }
6945: if (targetJDK < ClassFileConstants.JDK1_5) {
6946: // pre 1.5, synthetic is an attribute, not a modifier
6947: // pre 1.5, varargs is an attribute, not a modifier (-target jsr14 mode)
6948: accessFlags &= ~(ClassFileConstants.AccSynthetic | ClassFileConstants.AccVarargs);
6949: }
6950: if ((methodBinding.tagBits & TagBits.ClearPrivateModifier) != 0) {
6951: accessFlags &= ~ClassFileConstants.AccPrivate;
6952: }
6953: contents[contentsOffset++] = (byte) (accessFlags >> 8);
6954: contents[contentsOffset++] = (byte) accessFlags;
6955: int nameIndex = constantPool
6956: .literalIndex(methodBinding.selector);
6957: contents[contentsOffset++] = (byte) (nameIndex >> 8);
6958: contents[contentsOffset++] = (byte) nameIndex;
6959: int descriptorIndex = constantPool.literalIndex(methodBinding
6960: .signature(this ));
6961: contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
6962: contents[contentsOffset++] = (byte) descriptorIndex;
6963: }
6964:
6965: /**
6966: * INTERNAL USE-ONLY
6967: * That method generates the method info header of a clinit:
6968: * The header consists in:
6969: * - the access flags (always default access + static)
6970: * - the name index of the method name (always <clinit>) inside the constant pool
6971: * - the descriptor index of the signature (always ()V) of the method inside the constant pool.
6972: */
6973: public void generateMethodInfoHeaderForClinit() {
6974: // check that there is enough space to write all the bytes for the method info corresponding
6975: // to the @methodBinding
6976: methodCount++; // add one more method
6977: if (contentsOffset + 10 >= this .contents.length) {
6978: resizeContents(10);
6979: }
6980: contents[contentsOffset++] = (byte) ((ClassFileConstants.AccDefault | ClassFileConstants.AccStatic) >> 8);
6981: contents[contentsOffset++] = (byte) (ClassFileConstants.AccDefault | ClassFileConstants.AccStatic);
6982: int nameIndex = constantPool.literalIndex(ConstantPool.Clinit);
6983: contents[contentsOffset++] = (byte) (nameIndex >> 8);
6984: contents[contentsOffset++] = (byte) nameIndex;
6985: int descriptorIndex = constantPool
6986: .literalIndex(ConstantPool.ClinitSignature);
6987: contents[contentsOffset++] = (byte) (descriptorIndex >> 8);
6988: contents[contentsOffset++] = (byte) descriptorIndex;
6989: // We know that we won't get more than 1 attribute: the code attribute
6990: contents[contentsOffset++] = 0;
6991: contents[contentsOffset++] = 1;
6992: }
6993:
6994: /**
6995: * INTERNAL USE-ONLY
6996: * Generate the byte for problem method infos that correspond to missing abstract methods.
6997: * http://dev.eclipse.org/bugs/show_bug.cgi?id=3179
6998: *
6999: * @param methodDeclarations Array of all missing abstract methods
7000: */
7001: public void generateMissingAbstractMethods(
7002: MethodDeclaration[] methodDeclarations,
7003: CompilationResult compilationResult) {
7004: if (methodDeclarations != null) {
7005: TypeDeclaration currentDeclaration = this .referenceBinding.scope.referenceContext;
7006: int typeDeclarationSourceStart = currentDeclaration
7007: .sourceStart();
7008: int typeDeclarationSourceEnd = currentDeclaration
7009: .sourceEnd();
7010: for (int i = 0, max = methodDeclarations.length; i < max; i++) {
7011: MethodDeclaration methodDeclaration = methodDeclarations[i];
7012: MethodBinding methodBinding = methodDeclaration.binding;
7013: String readableName = new String(methodBinding
7014: .readableName());
7015: CategorizedProblem[] problems = compilationResult.problems;
7016: int problemsCount = compilationResult.problemCount;
7017: for (int j = 0; j < problemsCount; j++) {
7018: CategorizedProblem problem = problems[j];
7019: if (problem != null
7020: && problem.getID() == IProblem.AbstractMethodMustBeImplemented
7021: && problem.getMessage().indexOf(
7022: readableName) != -1
7023: && problem.getSourceStart() >= typeDeclarationSourceStart
7024: && problem.getSourceEnd() <= typeDeclarationSourceEnd) {
7025: // we found a match
7026: addMissingAbstractProblemMethod(
7027: methodDeclaration, methodBinding,
7028: problem, compilationResult);
7029: }
7030: }
7031: }
7032: }
7033: }
7034:
7035: /**
7036: * @param annotations
7037: * @return the number of attributes created while dumping the annotations in the .class file
7038: */
7039: private int generateRuntimeAnnotations(
7040: final Annotation[] annotations) {
7041: int attributesNumber = 0;
7042: final int length = annotations.length;
7043: int visibleAnnotationsCounter = 0;
7044: int invisibleAnnotationsCounter = 0;
7045:
7046: for (int i = 0; i < length; i++) {
7047: Annotation annotation = annotations[i];
7048: if (isRuntimeInvisible(annotation)) {
7049: invisibleAnnotationsCounter++;
7050: } else if (isRuntimeVisible(annotation)) {
7051: visibleAnnotationsCounter++;
7052: }
7053: }
7054:
7055: if (invisibleAnnotationsCounter != 0) {
7056: int annotationAttributeOffset = contentsOffset;
7057: if (contentsOffset + 10 >= contents.length) {
7058: resizeContents(10);
7059: }
7060: int runtimeInvisibleAnnotationsAttributeNameIndex = constantPool
7061: .literalIndex(AttributeNamesConstants.RuntimeInvisibleAnnotationsName);
7062: contents[contentsOffset++] = (byte) (runtimeInvisibleAnnotationsAttributeNameIndex >> 8);
7063: contents[contentsOffset++] = (byte) runtimeInvisibleAnnotationsAttributeNameIndex;
7064: int attributeLengthOffset = contentsOffset;
7065: contentsOffset += 4; // leave space for the attribute length
7066:
7067: int annotationsLengthOffset = contentsOffset;
7068: contentsOffset += 2; // leave space for the annotations length
7069:
7070: contents[annotationsLengthOffset++] = (byte) (invisibleAnnotationsCounter >> 8);
7071: contents[annotationsLengthOffset++] = (byte) invisibleAnnotationsCounter;
7072:
7073: loop: for (int i = 0; i < length; i++) {
7074: if (invisibleAnnotationsCounter == 0)
7075: break loop;
7076: Annotation annotation = annotations[i];
7077: if (isRuntimeInvisible(annotation)) {
7078: generateAnnotation(annotation,
7079: annotationAttributeOffset);
7080: invisibleAnnotationsCounter--;
7081: if (this .contentsOffset == annotationAttributeOffset) {
7082: break loop;
7083: }
7084: }
7085: }
7086: if (contentsOffset != annotationAttributeOffset) {
7087: int attributeLength = contentsOffset
7088: - attributeLengthOffset - 4;
7089: contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
7090: contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
7091: contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
7092: contents[attributeLengthOffset++] = (byte) attributeLength;
7093: attributesNumber++;
7094: } else {
7095: contentsOffset = annotationAttributeOffset;
7096: }
7097: }
7098:
7099: if (visibleAnnotationsCounter != 0) {
7100: int annotationAttributeOffset = contentsOffset;
7101: if (contentsOffset + 10 >= contents.length) {
7102: resizeContents(10);
7103: }
7104: int runtimeVisibleAnnotationsAttributeNameIndex = constantPool
7105: .literalIndex(AttributeNamesConstants.RuntimeVisibleAnnotationsName);
7106: contents[contentsOffset++] = (byte) (runtimeVisibleAnnotationsAttributeNameIndex >> 8);
7107: contents[contentsOffset++] = (byte) runtimeVisibleAnnotationsAttributeNameIndex;
7108: int attributeLengthOffset = contentsOffset;
7109: contentsOffset += 4; // leave space for the attribute length
7110:
7111: int annotationsLengthOffset = contentsOffset;
7112: contentsOffset += 2; // leave space for the annotations length
7113:
7114: contents[annotationsLengthOffset++] = (byte) (visibleAnnotationsCounter >> 8);
7115: contents[annotationsLengthOffset++] = (byte) visibleAnnotationsCounter;
7116:
7117: loop: for (int i = 0; i < length; i++) {
7118: if (visibleAnnotationsCounter == 0)
7119: break loop;
7120: Annotation annotation = annotations[i];
7121: if (isRuntimeVisible(annotation)) {
7122: visibleAnnotationsCounter--;
7123: generateAnnotation(annotation,
7124: annotationAttributeOffset);
7125: if (this .contentsOffset == annotationAttributeOffset) {
7126: break loop;
7127: }
7128: }
7129: }
7130: if (contentsOffset != annotationAttributeOffset) {
7131: int attributeLength = contentsOffset
7132: - attributeLengthOffset - 4;
7133: contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
7134: contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
7135: contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
7136: contents[attributeLengthOffset++] = (byte) attributeLength;
7137: attributesNumber++;
7138: } else {
7139: contentsOffset = annotationAttributeOffset;
7140: }
7141: }
7142: return attributesNumber;
7143: }
7144:
7145: private int generateRuntimeAnnotationsForParameters(
7146: Argument[] arguments) {
7147: final int argumentsLength = arguments.length;
7148: final int VISIBLE_INDEX = 0;
7149: final int INVISIBLE_INDEX = 1;
7150: int invisibleParametersAnnotationsCounter = 0;
7151: int visibleParametersAnnotationsCounter = 0;
7152: int[][] annotationsCounters = new int[argumentsLength][2];
7153: for (int i = 0; i < argumentsLength; i++) {
7154: Argument argument = arguments[i];
7155: Annotation[] annotations = argument.annotations;
7156: if (annotations != null) {
7157: for (int j = 0, max2 = annotations.length; j < max2; j++) {
7158: Annotation annotation = annotations[j];
7159: if (isRuntimeInvisible(annotation)) {
7160: annotationsCounters[i][INVISIBLE_INDEX]++;
7161: invisibleParametersAnnotationsCounter++;
7162: } else if (isRuntimeVisible(annotation)) {
7163: annotationsCounters[i][VISIBLE_INDEX]++;
7164: visibleParametersAnnotationsCounter++;
7165: }
7166: }
7167: }
7168: }
7169: int attributesNumber = 0;
7170: int annotationAttributeOffset = contentsOffset;
7171: if (invisibleParametersAnnotationsCounter != 0) {
7172: if (contentsOffset + 7 >= contents.length) {
7173: resizeContents(7);
7174: }
7175: int attributeNameIndex = constantPool
7176: .literalIndex(AttributeNamesConstants.RuntimeInvisibleParameterAnnotationsName);
7177: contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
7178: contents[contentsOffset++] = (byte) attributeNameIndex;
7179: int attributeLengthOffset = contentsOffset;
7180: contentsOffset += 4; // leave space for the attribute length
7181:
7182: contents[contentsOffset++] = (byte) argumentsLength;
7183: invisibleLoop: for (int i = 0; i < argumentsLength; i++) {
7184: if (contentsOffset + 2 >= contents.length) {
7185: resizeContents(2);
7186: }
7187: if (invisibleParametersAnnotationsCounter == 0) {
7188: contents[contentsOffset++] = (byte) 0;
7189: contents[contentsOffset++] = (byte) 0;
7190: } else {
7191: final int numberOfInvisibleAnnotations = annotationsCounters[i][INVISIBLE_INDEX];
7192: contents[contentsOffset++] = (byte) (numberOfInvisibleAnnotations >> 8);
7193: contents[contentsOffset++] = (byte) numberOfInvisibleAnnotations;
7194: if (numberOfInvisibleAnnotations != 0) {
7195: Argument argument = arguments[i];
7196: Annotation[] annotations = argument.annotations;
7197: for (int j = 0, max = annotations.length; j < max; j++) {
7198: Annotation annotation = annotations[j];
7199: if (isRuntimeInvisible(annotation)) {
7200: generateAnnotation(annotation,
7201: annotationAttributeOffset);
7202: if (contentsOffset == annotationAttributeOffset) {
7203: break invisibleLoop;
7204: }
7205: invisibleParametersAnnotationsCounter--;
7206: }
7207: }
7208: }
7209: }
7210: }
7211: if (contentsOffset != annotationAttributeOffset) {
7212: int attributeLength = contentsOffset
7213: - attributeLengthOffset - 4;
7214: contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
7215: contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
7216: contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
7217: contents[attributeLengthOffset++] = (byte) attributeLength;
7218: attributesNumber++;
7219: } else {
7220: contentsOffset = annotationAttributeOffset;
7221: }
7222: }
7223: if (visibleParametersAnnotationsCounter != 0) {
7224: if (contentsOffset + 7 >= contents.length) {
7225: resizeContents(7);
7226: }
7227: int attributeNameIndex = constantPool
7228: .literalIndex(AttributeNamesConstants.RuntimeVisibleParameterAnnotationsName);
7229: contents[contentsOffset++] = (byte) (attributeNameIndex >> 8);
7230: contents[contentsOffset++] = (byte) attributeNameIndex;
7231: int attributeLengthOffset = contentsOffset;
7232: contentsOffset += 4; // leave space for the attribute length
7233:
7234: contents[contentsOffset++] = (byte) argumentsLength;
7235: visibleLoop: for (int i = 0; i < argumentsLength; i++) {
7236: if (contentsOffset + 2 >= contents.length) {
7237: resizeContents(2);
7238: }
7239: if (visibleParametersAnnotationsCounter == 0) {
7240: contents[contentsOffset++] = (byte) 0;
7241: contents[contentsOffset++] = (byte) 0;
7242: } else {
7243: final int numberOfVisibleAnnotations = annotationsCounters[i][VISIBLE_INDEX];
7244: contents[contentsOffset++] = (byte) (numberOfVisibleAnnotations >> 8);
7245: contents[contentsOffset++] = (byte) numberOfVisibleAnnotations;
7246: if (numberOfVisibleAnnotations != 0) {
7247: Argument argument = arguments[i];
7248: Annotation[] annotations = argument.annotations;
7249: for (int j = 0, max = annotations.length; j < max; j++) {
7250: Annotation annotation = annotations[j];
7251: if (isRuntimeVisible(annotation)) {
7252: generateAnnotation(annotation,
7253: annotationAttributeOffset);
7254: if (contentsOffset == annotationAttributeOffset) {
7255: break visibleLoop;
7256: }
7257: visibleParametersAnnotationsCounter--;
7258: }
7259: }
7260: }
7261: }
7262: }
7263: if (contentsOffset != annotationAttributeOffset) {
7264: int attributeLength = contentsOffset
7265: - attributeLengthOffset - 4;
7266: contents[attributeLengthOffset++] = (byte) (attributeLength >> 24);
7267: contents[attributeLengthOffset++] = (byte) (attributeLength >> 16);
7268: contents[attributeLengthOffset++] = (byte) (attributeLength >> 8);
7269: contents[attributeLengthOffset++] = (byte) attributeLength;
7270: attributesNumber++;
7271: } else {
7272: contentsOffset = annotationAttributeOffset;
7273: }
7274: }
7275: return attributesNumber;
7276: }
7277:
7278: /**
7279: * EXTERNAL API
7280: * Answer the actual bytes of the class file
7281: *
7282: * This method encodes the receiver structure into a byte array which is the content of the classfile.
7283: * Returns the byte array that represents the encoded structure of the receiver.
7284: *
7285: * @return byte[]
7286: */
7287: public byte[] getBytes() {
7288: if (this .bytes == null) {
7289: this .bytes = new byte[this .headerOffset
7290: + this .contentsOffset];
7291: System.arraycopy(this .header, 0, this .bytes, 0,
7292: this .headerOffset);
7293: System.arraycopy(this .contents, 0, this .bytes,
7294: this .headerOffset, this .contentsOffset);
7295: }
7296: return this .bytes;
7297: }
7298:
7299: /**
7300: * EXTERNAL API
7301: * Answer the compound name of the class file.
7302: * @return char[][]
7303: * e.g. {{java}, {util}, {Hashtable}}.
7304: */
7305: public char[][] getCompoundName() {
7306: return CharOperation.splitOn('/', fileName());
7307: }
7308:
7309: protected void initByteArrays() {
7310: int members = referenceBinding.methods().length
7311: + referenceBinding.fields().length;
7312: this .header = new byte[INITIAL_HEADER_SIZE];
7313: this .contents = new byte[members < 15 ? INITIAL_CONTENTS_SIZE
7314: : INITIAL_HEADER_SIZE];
7315: }
7316:
7317: public void initialize(SourceTypeBinding aType,
7318: ClassFile parentClassFile, boolean createProblemType) {
7319: // generate the magic numbers inside the header
7320: header[headerOffset++] = (byte) (0xCAFEBABEL >> 24);
7321: header[headerOffset++] = (byte) (0xCAFEBABEL >> 16);
7322: header[headerOffset++] = (byte) (0xCAFEBABEL >> 8);
7323: header[headerOffset++] = (byte) (0xCAFEBABEL >> 0);
7324:
7325: header[headerOffset++] = (byte) (this .targetJDK >> 8); // minor high
7326: header[headerOffset++] = (byte) (this .targetJDK >> 0); // minor low
7327: header[headerOffset++] = (byte) (this .targetJDK >> 24); // major high
7328: header[headerOffset++] = (byte) (this .targetJDK >> 16); // major low
7329:
7330: constantPoolOffset = headerOffset;
7331: headerOffset += 2;
7332: this .constantPool.initialize(this );
7333:
7334: // Modifier manipulations for classfile
7335: int accessFlags = aType.getAccessFlags();
7336: if (aType.isPrivate()) { // rewrite private to non-public
7337: accessFlags &= ~ClassFileConstants.AccPublic;
7338: }
7339: if (aType.isProtected()) { // rewrite protected into public
7340: accessFlags |= ClassFileConstants.AccPublic;
7341: }
7342: // clear all bits that are illegal for a class or an interface
7343: accessFlags &= ~(ClassFileConstants.AccStrictfp
7344: | ClassFileConstants.AccProtected
7345: | ClassFileConstants.AccPrivate
7346: | ClassFileConstants.AccStatic
7347: | ClassFileConstants.AccSynchronized | ClassFileConstants.AccNative);
7348:
7349: // set the AccSuper flag (has to be done after clearing AccSynchronized - since same value)
7350: if (!aType.isInterface()) { // class or enum
7351: accessFlags |= ClassFileConstants.AccSuper;
7352: }
7353:
7354: this .enclosingClassFile = parentClassFile;
7355: // innerclasses get their names computed at code gen time
7356:
7357: // now we continue to generate the bytes inside the contents array
7358: contents[contentsOffset++] = (byte) (accessFlags >> 8);
7359: contents[contentsOffset++] = (byte) accessFlags;
7360: int classNameIndex = constantPool.literalIndexForType(aType);
7361: contents[contentsOffset++] = (byte) (classNameIndex >> 8);
7362: contents[contentsOffset++] = (byte) classNameIndex;
7363: int super classNameIndex;
7364: if (aType.isInterface()) {
7365: super classNameIndex = constantPool
7366: .literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName);
7367: } else {
7368: super classNameIndex = (aType.super class == null ? 0
7369: : constantPool
7370: .literalIndexForType(aType.super class));
7371: }
7372: contents[contentsOffset++] = (byte) (super classNameIndex >> 8);
7373: contents[contentsOffset++] = (byte) super classNameIndex;
7374: ReferenceBinding[] super InterfacesBinding = aType
7375: .super Interfaces();
7376: int interfacesCount = super InterfacesBinding.length;
7377: contents[contentsOffset++] = (byte) (interfacesCount >> 8);
7378: contents[contentsOffset++] = (byte) interfacesCount;
7379: for (int i = 0; i < interfacesCount; i++) {
7380: int interfaceIndex = constantPool
7381: .literalIndexForType(super InterfacesBinding[i]);
7382: contents[contentsOffset++] = (byte) (interfaceIndex >> 8);
7383: contents[contentsOffset++] = (byte) interfaceIndex;
7384: }
7385: this .creatingProblemType = createProblemType;
7386:
7387: // retrieve the enclosing one guaranteed to be the one matching the propagated flow info
7388: // 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check)
7389: if (this .enclosingClassFile == null) {
7390: this .codeStream.maxFieldCount = aType.scope.referenceType().maxFieldCount;
7391: } else {
7392: ClassFile outermostClassFile = this
7393: .outerMostEnclosingClassFile();
7394: this .codeStream.maxFieldCount = outermostClassFile.codeStream.maxFieldCount;
7395: }
7396: }
7397:
7398: private boolean isRuntimeInvisible(Annotation annotation) {
7399: final TypeBinding annotationBinding = annotation.resolvedType;
7400: if (annotationBinding == null) {
7401: return false;
7402: }
7403: long metaTagBits = annotationBinding.getAnnotationTagBits(); // could be forward reference
7404: if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
7405: return true; // by default the retention is CLASS
7406:
7407: return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationClassRetention;
7408: }
7409:
7410: private boolean isRuntimeVisible(Annotation annotation) {
7411: final TypeBinding annotationBinding = annotation.resolvedType;
7412: if (annotationBinding == null) {
7413: return false;
7414: }
7415: long metaTagBits = annotationBinding.getAnnotationTagBits();
7416: if ((metaTagBits & TagBits.AnnotationRetentionMASK) == 0)
7417: return false; // by default the retention is CLASS
7418:
7419: return (metaTagBits & TagBits.AnnotationRetentionMASK) == TagBits.AnnotationRuntimeRetention;
7420: }
7421:
7422: /**
7423: * INTERNAL USE-ONLY
7424: * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name
7425: * for all inner types of the receiver.
7426: * @return org.eclipse.jdt.internal.compiler.codegen.ClassFile
7427: */
7428: public ClassFile outerMostEnclosingClassFile() {
7429: ClassFile current = this ;
7430: while (current.enclosingClassFile != null)
7431: current = current.enclosingClassFile;
7432: return current;
7433: }
7434:
7435: public void recordInnerClasses(TypeBinding binding) {
7436: if (this .innerClassesBindings == null) {
7437: this .innerClassesBindings = new HashSet(INNER_CLASSES_SIZE);
7438: }
7439: ReferenceBinding innerClass = (ReferenceBinding) binding;
7440: this .innerClassesBindings.add(innerClass.erasure());
7441: ReferenceBinding enclosingType = innerClass.enclosingType();
7442: while (enclosingType != null && enclosingType.isNestedType()) {
7443: this .innerClassesBindings.add(enclosingType.erasure());
7444: enclosingType = enclosingType.enclosingType();
7445: }
7446: }
7447:
7448: public void reset(SourceTypeBinding typeBinding) {
7449: // the code stream is reinitialized for each method
7450: final CompilerOptions options = typeBinding.scope
7451: .compilerOptions();
7452: this .referenceBinding = typeBinding;
7453: this .targetJDK = options.targetJDK;
7454: this .produceAttributes = options.produceDebugAttributes;
7455: if (this .targetJDK >= ClassFileConstants.JDK1_6) {
7456: this .produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE;
7457: } else if (this .targetJDK == ClassFileConstants.CLDC_1_1) {
7458: this .targetJDK = ClassFileConstants.JDK1_1; // put back 45.3
7459: this .produceAttributes |= ClassFileConstants.ATTR_STACK_MAP;
7460: }
7461: this .bytes = null;
7462: this .constantPool.reset();
7463: this .codeStream.reset(this );
7464: this .constantPoolOffset = 0;
7465: this .contentsOffset = 0;
7466: this .creatingProblemType = false;
7467: this .enclosingClassFile = null;
7468: this .headerOffset = 0;
7469: this .methodCount = 0;
7470: this .methodCountOffset = 0;
7471: if (this .innerClassesBindings != null) {
7472: this .innerClassesBindings.clear();
7473: }
7474: }
7475:
7476: /**
7477: * Resize the pool contents
7478: */
7479: private final void resizeContents(int minimalSize) {
7480: int length = this .contents.length;
7481: int toAdd = length;
7482: if (toAdd < minimalSize)
7483: toAdd = minimalSize;
7484: System.arraycopy(this .contents, 0,
7485: this .contents = new byte[length + toAdd], 0, length);
7486: }
7487:
7488: /**
7489: * INTERNAL USE-ONLY
7490: * This methods leaves the space for method counts recording.
7491: */
7492: public void setForMethodInfos() {
7493: // leave some space for the methodCount
7494: methodCountOffset = contentsOffset;
7495: contentsOffset += 2;
7496: }
7497:
7498: public void traverse(MethodBinding methodBinding, int maxLocals,
7499: byte[] bytecodes, int codeOffset, int codeLength,
7500: ArrayList frames, boolean isClinit) {
7501: StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this .codeStream;
7502: int[] framePositions = stackMapFrameCodeStream
7503: .getFramePositions();
7504: int pc = codeOffset;
7505: int index;
7506: int[] constantPoolOffsets = this .constantPool.offsets;
7507: byte[] poolContents = this .constantPool.poolContent;
7508:
7509: // set initial values for frame positions
7510: int indexInFramePositions = 0;
7511: int framePositionsLength = framePositions.length;
7512: int currentFramePosition = framePositions[0];
7513:
7514: // set initial values for stack markers
7515: int indexInStackMarkers = 0;
7516: ArrayList stackMarkers = stackMapFrameCodeStream.stackMarkers;
7517: boolean hasStackMarkers = stackMarkers != null
7518: && stackMarkers.size() != 0;
7519: StackMarker[] markers = null;
7520: int markersLength = 0;
7521: StackMarker marker = null;
7522: if (hasStackMarkers) {
7523: markersLength = stackMarkers.size();
7524: stackMarkers
7525: .toArray(markers = new StackMarker[markersLength]);
7526: marker = markers[0];
7527: }
7528:
7529: // set initial values for exception markers
7530: int indexInExceptionMarkers = 0;
7531: ExceptionMarker[] exceptionMarkers = stackMapFrameCodeStream
7532: .getExceptionMarkers();
7533: boolean hasExceptionMarkers = exceptionMarkers != null
7534: && exceptionMarkers.length != 0;
7535: int exceptionsMarkersLength = 0;
7536: ExceptionMarker exceptionMarker = null;
7537: if (hasExceptionMarkers) {
7538: exceptionsMarkersLength = exceptionMarkers.length;
7539: exceptionMarker = exceptionMarkers[0];
7540: }
7541:
7542: StackMapFrame frame = new StackMapFrame(maxLocals);
7543: if (!isClinit) {
7544: initializeDefaultLocals(frame, methodBinding, maxLocals,
7545: codeLength);
7546: }
7547: frame.pc = -1;
7548: frames.add(frame.duplicate());
7549: while (true) {
7550: int currentPC = pc - codeOffset;
7551: if (hasStackMarkers && marker.pc == currentPC) {
7552: TypeBinding typeBinding = marker.typeBinding;
7553: if (typeBinding != null) {
7554: if (marker.delta > 0) {
7555: frame.addStackItem(new VerificationTypeInfo(
7556: typeBinding));
7557: } else {
7558: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
7559: typeBinding);
7560: }
7561: } else {
7562: frame.numberOfStackItems--;
7563: }
7564: indexInStackMarkers++;
7565: if (indexInStackMarkers < markersLength) {
7566: marker = markers[indexInStackMarkers];
7567: } else {
7568: hasStackMarkers = false;
7569: }
7570: }
7571: if (hasExceptionMarkers && exceptionMarker.pc == currentPC) {
7572: frame.addStackItem(new VerificationTypeInfo(0,
7573: VerificationTypeInfo.ITEM_OBJECT,
7574: exceptionMarker.constantPoolName));
7575: indexInExceptionMarkers++;
7576: if (indexInExceptionMarkers < exceptionsMarkersLength) {
7577: exceptionMarker = exceptionMarkers[indexInExceptionMarkers];
7578: } else {
7579: hasExceptionMarkers = false;
7580: }
7581: }
7582: if (currentFramePosition < currentPC) {
7583: do {
7584: indexInFramePositions++;
7585: if (indexInFramePositions < framePositionsLength) {
7586: currentFramePosition = framePositions[indexInFramePositions];
7587: } else {
7588: // no more frame to generate
7589: return;
7590: }
7591: } while (currentFramePosition < currentPC);
7592: }
7593: if (currentFramePosition == currentPC) {
7594: // need to build a new frame and create a stack map attribute entry
7595: StackMapFrame currentFrame = frame.duplicate();
7596: currentFrame.pc = currentPC;
7597: // initialize locals
7598: initializeLocals(isClinit ? true : methodBinding
7599: .isStatic(), currentPC, currentFrame);
7600: // insert a new frame
7601: frames.add(currentFrame);
7602: indexInFramePositions++;
7603: if (indexInFramePositions < framePositionsLength) {
7604: currentFramePosition = framePositions[indexInFramePositions];
7605: } else {
7606: // no more frame to generate
7607: return;
7608: }
7609: }
7610: byte opcode = (byte) u1At(bytecodes, 0, pc);
7611: switch (opcode) {
7612: case Opcodes.OPC_nop:
7613: pc++;
7614: break;
7615: case Opcodes.OPC_aconst_null:
7616: frame.addStackItem(TypeBinding.NULL);
7617: pc++;
7618: break;
7619: case Opcodes.OPC_iconst_m1:
7620: case Opcodes.OPC_iconst_0:
7621: case Opcodes.OPC_iconst_1:
7622: case Opcodes.OPC_iconst_2:
7623: case Opcodes.OPC_iconst_3:
7624: case Opcodes.OPC_iconst_4:
7625: case Opcodes.OPC_iconst_5:
7626: frame.addStackItem(TypeBinding.INT);
7627: pc++;
7628: break;
7629: case Opcodes.OPC_lconst_0:
7630: case Opcodes.OPC_lconst_1:
7631: frame.addStackItem(TypeBinding.LONG);
7632: pc++;
7633: break;
7634: case Opcodes.OPC_fconst_0:
7635: case Opcodes.OPC_fconst_1:
7636: case Opcodes.OPC_fconst_2:
7637: frame.addStackItem(TypeBinding.FLOAT);
7638: pc++;
7639: break;
7640: case Opcodes.OPC_dconst_0:
7641: case Opcodes.OPC_dconst_1:
7642: frame.addStackItem(TypeBinding.DOUBLE);
7643: pc++;
7644: break;
7645: case Opcodes.OPC_bipush:
7646: frame.addStackItem(TypeBinding.BYTE);
7647: pc += 2;
7648: break;
7649: case Opcodes.OPC_sipush:
7650: frame.addStackItem(TypeBinding.SHORT);
7651: pc += 3;
7652: break;
7653: case Opcodes.OPC_ldc:
7654: index = u1At(bytecodes, 1, pc);
7655: switch (u1At(poolContents, 0,
7656: constantPoolOffsets[index])) {
7657: case ClassFileConstants.StringTag:
7658: frame
7659: .addStackItem(new VerificationTypeInfo(
7660: TypeIds.T_JavaLangString,
7661: ConstantPool.JavaLangStringConstantPoolName));
7662: break;
7663: case ClassFileConstants.IntegerTag:
7664: frame.addStackItem(TypeBinding.INT);
7665: break;
7666: case ClassFileConstants.FloatTag:
7667: frame.addStackItem(TypeBinding.FLOAT);
7668: break;
7669: case ClassFileConstants.ClassTag:
7670: int utf8index = u2At(poolContents, 1,
7671: constantPoolOffsets[index]);
7672: char[] classSignature = utf8At(poolContents,
7673: constantPoolOffsets[utf8index] + 3, u2At(
7674: poolContents, 1,
7675: constantPoolOffsets[utf8index]));
7676: frame.addStackItem(new VerificationTypeInfo(0,
7677: classSignature));
7678: }
7679: pc += 2;
7680: break;
7681: case Opcodes.OPC_ldc_w:
7682: index = u2At(bytecodes, 1, pc);
7683: switch (u1At(poolContents, 0,
7684: constantPoolOffsets[index])) {
7685: case ClassFileConstants.StringTag:
7686: frame
7687: .addStackItem(new VerificationTypeInfo(
7688: TypeIds.T_JavaLangString,
7689: ConstantPool.JavaLangStringConstantPoolName));
7690: break;
7691: case ClassFileConstants.IntegerTag:
7692: frame.addStackItem(TypeBinding.INT);
7693: break;
7694: case ClassFileConstants.FloatTag:
7695: frame.addStackItem(TypeBinding.FLOAT);
7696: break;
7697: case ClassFileConstants.ClassTag:
7698: int utf8index = u2At(poolContents, 1,
7699: constantPoolOffsets[index]);
7700: char[] classSignature = utf8At(poolContents,
7701: constantPoolOffsets[utf8index] + 3, u2At(
7702: poolContents, 1,
7703: constantPoolOffsets[utf8index]));
7704: frame.addStackItem(new VerificationTypeInfo(0,
7705: classSignature));
7706: }
7707: pc += 3;
7708: break;
7709: case Opcodes.OPC_ldc2_w:
7710: index = u2At(bytecodes, 1, pc);
7711: switch (u1At(poolContents, 0,
7712: constantPoolOffsets[index])) {
7713: case ClassFileConstants.DoubleTag:
7714: frame.addStackItem(TypeBinding.DOUBLE);
7715: break;
7716: case ClassFileConstants.LongTag:
7717: frame.addStackItem(TypeBinding.LONG);
7718: break;
7719: }
7720: pc += 3;
7721: break;
7722: case Opcodes.OPC_iload:
7723: frame.addStackItem(TypeBinding.INT);
7724: pc += 2;
7725: break;
7726: case Opcodes.OPC_lload:
7727: frame.addStackItem(TypeBinding.LONG);
7728: pc += 2;
7729: break;
7730: case Opcodes.OPC_fload:
7731: frame.addStackItem(TypeBinding.FLOAT);
7732: pc += 2;
7733: break;
7734: case Opcodes.OPC_dload:
7735: frame.addStackItem(TypeBinding.DOUBLE);
7736: pc += 2;
7737: break;
7738: case Opcodes.OPC_aload:
7739: index = u1At(bytecodes, 1, pc);
7740: VerificationTypeInfo localsN = frame.locals[index];
7741: if (localsN == null) {
7742: localsN = retrieveLocal(currentPC, index);
7743: }
7744: frame.addStackItem(localsN);
7745: pc += 2;
7746: break;
7747: case Opcodes.OPC_iload_0:
7748: case Opcodes.OPC_iload_1:
7749: case Opcodes.OPC_iload_2:
7750: case Opcodes.OPC_iload_3:
7751: frame.addStackItem(TypeBinding.INT);
7752: pc++;
7753: break;
7754: case Opcodes.OPC_lload_0:
7755: case Opcodes.OPC_lload_1:
7756: case Opcodes.OPC_lload_2:
7757: case Opcodes.OPC_lload_3:
7758: frame.addStackItem(TypeBinding.LONG);
7759: pc++;
7760: break;
7761: case Opcodes.OPC_fload_0:
7762: case Opcodes.OPC_fload_1:
7763: case Opcodes.OPC_fload_2:
7764: case Opcodes.OPC_fload_3:
7765: frame.addStackItem(TypeBinding.FLOAT);
7766: pc++;
7767: break;
7768: case Opcodes.OPC_dload_0:
7769: case Opcodes.OPC_dload_1:
7770: case Opcodes.OPC_dload_2:
7771: case Opcodes.OPC_dload_3:
7772: frame.addStackItem(TypeBinding.DOUBLE);
7773: pc++;
7774: break;
7775: case Opcodes.OPC_aload_0:
7776: VerificationTypeInfo locals0 = frame.locals[0];
7777: // special case to handle uninitialized object
7778: if (locals0 == null) {
7779: locals0 = retrieveLocal(currentPC, 0);
7780: }
7781: frame.addStackItem(locals0);
7782: pc++;
7783: break;
7784: case Opcodes.OPC_aload_1:
7785: VerificationTypeInfo locals1 = retrieveLocal(currentPC,
7786: 1);
7787: frame.addStackItem(locals1);
7788: pc++;
7789: break;
7790: case Opcodes.OPC_aload_2:
7791: VerificationTypeInfo locals2 = retrieveLocal(currentPC,
7792: 2);
7793: frame.addStackItem(locals2);
7794: pc++;
7795: break;
7796: case Opcodes.OPC_aload_3:
7797: VerificationTypeInfo locals3 = retrieveLocal(currentPC,
7798: 3);
7799: frame.addStackItem(locals3);
7800: pc++;
7801: break;
7802: case Opcodes.OPC_iaload:
7803: frame.numberOfStackItems -= 2;
7804: frame.addStackItem(TypeBinding.INT);
7805: pc++;
7806: break;
7807: case Opcodes.OPC_laload:
7808: frame.numberOfStackItems -= 2;
7809: frame.addStackItem(TypeBinding.LONG);
7810: pc++;
7811: break;
7812: case Opcodes.OPC_faload:
7813: frame.numberOfStackItems -= 2;
7814: frame.addStackItem(TypeBinding.FLOAT);
7815: pc++;
7816: break;
7817: case Opcodes.OPC_daload:
7818: frame.numberOfStackItems -= 2;
7819: frame.addStackItem(TypeBinding.DOUBLE);
7820: pc++;
7821: break;
7822: case Opcodes.OPC_aaload:
7823: frame.numberOfStackItems--;
7824: frame.replaceWithElementType();
7825: pc++;
7826: break;
7827: case Opcodes.OPC_baload:
7828: frame.numberOfStackItems -= 2;
7829: frame.addStackItem(TypeBinding.BYTE);
7830: pc++;
7831: break;
7832: case Opcodes.OPC_caload:
7833: frame.numberOfStackItems -= 2;
7834: frame.addStackItem(TypeBinding.CHAR);
7835: pc++;
7836: break;
7837: case Opcodes.OPC_saload:
7838: frame.numberOfStackItems -= 2;
7839: frame.addStackItem(TypeBinding.SHORT);
7840: pc++;
7841: break;
7842: case Opcodes.OPC_istore:
7843: case Opcodes.OPC_lstore:
7844: case Opcodes.OPC_fstore:
7845: case Opcodes.OPC_dstore:
7846: frame.numberOfStackItems--;
7847: pc += 2;
7848: break;
7849: case Opcodes.OPC_astore:
7850: index = u1At(bytecodes, 1, pc);
7851: frame.numberOfStackItems--;
7852: pc += 2;
7853: break;
7854: case Opcodes.OPC_astore_0:
7855: frame.locals[0] = frame.stackItems[frame.numberOfStackItems - 1];
7856: frame.numberOfStackItems--;
7857: pc++;
7858: break;
7859: case Opcodes.OPC_astore_1:
7860: case Opcodes.OPC_astore_2:
7861: case Opcodes.OPC_astore_3:
7862: case Opcodes.OPC_istore_0:
7863: case Opcodes.OPC_istore_1:
7864: case Opcodes.OPC_istore_2:
7865: case Opcodes.OPC_istore_3:
7866: case Opcodes.OPC_lstore_0:
7867: case Opcodes.OPC_lstore_1:
7868: case Opcodes.OPC_lstore_2:
7869: case Opcodes.OPC_lstore_3:
7870: case Opcodes.OPC_fstore_0:
7871: case Opcodes.OPC_fstore_1:
7872: case Opcodes.OPC_fstore_2:
7873: case Opcodes.OPC_fstore_3:
7874: case Opcodes.OPC_dstore_0:
7875: case Opcodes.OPC_dstore_1:
7876: case Opcodes.OPC_dstore_2:
7877: case Opcodes.OPC_dstore_3:
7878: frame.numberOfStackItems--;
7879: pc++;
7880: break;
7881: case Opcodes.OPC_iastore:
7882: case Opcodes.OPC_lastore:
7883: case Opcodes.OPC_fastore:
7884: case Opcodes.OPC_dastore:
7885: case Opcodes.OPC_aastore:
7886: case Opcodes.OPC_bastore:
7887: case Opcodes.OPC_castore:
7888: case Opcodes.OPC_sastore:
7889: frame.numberOfStackItems -= 3;
7890: pc++;
7891: break;
7892: case Opcodes.OPC_pop:
7893: frame.numberOfStackItems--;
7894: pc++;
7895: break;
7896: case Opcodes.OPC_pop2:
7897: int numberOfStackItems = frame.numberOfStackItems;
7898: switch (frame.stackItems[numberOfStackItems - 1].id()) {
7899: case TypeIds.T_long:
7900: case TypeIds.T_double:
7901: frame.numberOfStackItems--;
7902: break;
7903: default:
7904: frame.numberOfStackItems -= 2;
7905: }
7906: pc++;
7907: break;
7908: case Opcodes.OPC_dup:
7909: frame
7910: .addStackItem(frame.stackItems[frame.numberOfStackItems - 1]);
7911: pc++;
7912: break;
7913: case Opcodes.OPC_dup_x1:
7914: VerificationTypeInfo info = frame.stackItems[frame.numberOfStackItems - 1];
7915: frame.numberOfStackItems--;
7916: VerificationTypeInfo info2 = frame.stackItems[frame.numberOfStackItems - 1];
7917: frame.numberOfStackItems--;
7918: frame.addStackItem(info);
7919: frame.addStackItem(info2);
7920: frame.addStackItem(info);
7921: pc++;
7922: break;
7923: case Opcodes.OPC_dup_x2:
7924: info = frame.stackItems[frame.numberOfStackItems - 1];
7925: frame.numberOfStackItems--;
7926: info2 = frame.stackItems[frame.numberOfStackItems - 1];
7927: frame.numberOfStackItems--;
7928: switch (info2.id()) {
7929: case TypeIds.T_long:
7930: case TypeIds.T_double:
7931: frame.addStackItem(info);
7932: frame.addStackItem(info2);
7933: frame.addStackItem(info);
7934: break;
7935: default:
7936: numberOfStackItems = frame.numberOfStackItems;
7937: VerificationTypeInfo info3 = frame.stackItems[numberOfStackItems - 1];
7938: frame.numberOfStackItems--;
7939: frame.addStackItem(info);
7940: frame.addStackItem(info3);
7941: frame.addStackItem(info2);
7942: frame.addStackItem(info);
7943: }
7944: pc++;
7945: break;
7946: case Opcodes.OPC_dup2:
7947: info = frame.stackItems[frame.numberOfStackItems - 1];
7948: frame.numberOfStackItems--;
7949: switch (info.id()) {
7950: case TypeIds.T_double:
7951: case TypeIds.T_long:
7952: frame.addStackItem(info);
7953: frame.addStackItem(info);
7954: break;
7955: default:
7956: info2 = frame.stackItems[frame.numberOfStackItems - 1];
7957: frame.numberOfStackItems--;
7958: frame.addStackItem(info2);
7959: frame.addStackItem(info);
7960: frame.addStackItem(info2);
7961: frame.addStackItem(info);
7962: }
7963: pc++;
7964: break;
7965: case Opcodes.OPC_dup2_x1:
7966: info = frame.stackItems[frame.numberOfStackItems - 1];
7967: frame.numberOfStackItems--;
7968: info2 = frame.stackItems[frame.numberOfStackItems - 1];
7969: frame.numberOfStackItems--;
7970: switch (info.id()) {
7971: case TypeIds.T_double:
7972: case TypeIds.T_long:
7973: frame.addStackItem(info);
7974: frame.addStackItem(info2);
7975: frame.addStackItem(info);
7976: break;
7977: default:
7978: VerificationTypeInfo info3 = frame.stackItems[frame.numberOfStackItems - 1];
7979: frame.numberOfStackItems--;
7980: frame.addStackItem(info2);
7981: frame.addStackItem(info);
7982: frame.addStackItem(info3);
7983: frame.addStackItem(info2);
7984: frame.addStackItem(info);
7985: }
7986: pc++;
7987: break;
7988: case Opcodes.OPC_dup2_x2:
7989: numberOfStackItems = frame.numberOfStackItems;
7990: info = frame.stackItems[numberOfStackItems - 1];
7991: frame.numberOfStackItems--;
7992: info2 = frame.stackItems[frame.numberOfStackItems - 1];
7993: frame.numberOfStackItems--;
7994: switch (info.id()) {
7995: case TypeIds.T_long:
7996: case TypeIds.T_double:
7997: switch (info2.id()) {
7998: case TypeIds.T_long:
7999: case TypeIds.T_double:
8000: // form 4
8001: frame.addStackItem(info);
8002: frame.addStackItem(info2);
8003: frame.addStackItem(info);
8004: break;
8005: default:
8006: // form 2
8007: numberOfStackItems = frame.numberOfStackItems;
8008: VerificationTypeInfo info3 = frame.stackItems[numberOfStackItems - 1];
8009: frame.numberOfStackItems--;
8010: frame.addStackItem(info);
8011: frame.addStackItem(info3);
8012: frame.addStackItem(info2);
8013: frame.addStackItem(info);
8014: }
8015: break;
8016: default:
8017: numberOfStackItems = frame.numberOfStackItems;
8018: VerificationTypeInfo info3 = frame.stackItems[numberOfStackItems - 1];
8019: frame.numberOfStackItems--;
8020: switch (info3.id()) {
8021: case TypeIds.T_long:
8022: case TypeIds.T_double:
8023: // form 3
8024: frame.addStackItem(info2);
8025: frame.addStackItem(info);
8026: frame.addStackItem(info3);
8027: frame.addStackItem(info2);
8028: frame.addStackItem(info);
8029: break;
8030: default:
8031: // form 1
8032: numberOfStackItems = frame.numberOfStackItems;
8033: VerificationTypeInfo info4 = frame.stackItems[numberOfStackItems - 1];
8034: frame.numberOfStackItems--;
8035: frame.addStackItem(info2);
8036: frame.addStackItem(info);
8037: frame.addStackItem(info4);
8038: frame.addStackItem(info3);
8039: frame.addStackItem(info2);
8040: frame.addStackItem(info);
8041: }
8042: }
8043: pc++;
8044: break;
8045: case Opcodes.OPC_swap:
8046: numberOfStackItems = frame.numberOfStackItems;
8047: info = frame.stackItems[numberOfStackItems - 1];
8048: info2 = frame.stackItems[numberOfStackItems - 2];
8049: frame.stackItems[numberOfStackItems - 1] = info2;
8050: frame.stackItems[numberOfStackItems - 2] = info;
8051: pc++;
8052: break;
8053: case Opcodes.OPC_iadd:
8054: case Opcodes.OPC_ladd:
8055: case Opcodes.OPC_fadd:
8056: case Opcodes.OPC_dadd:
8057: case Opcodes.OPC_isub:
8058: case Opcodes.OPC_lsub:
8059: case Opcodes.OPC_fsub:
8060: case Opcodes.OPC_dsub:
8061: case Opcodes.OPC_imul:
8062: case Opcodes.OPC_lmul:
8063: case Opcodes.OPC_fmul:
8064: case Opcodes.OPC_dmul:
8065: case Opcodes.OPC_idiv:
8066: case Opcodes.OPC_ldiv:
8067: case Opcodes.OPC_fdiv:
8068: case Opcodes.OPC_ddiv:
8069: case Opcodes.OPC_irem:
8070: case Opcodes.OPC_lrem:
8071: case Opcodes.OPC_frem:
8072: case Opcodes.OPC_drem:
8073: case Opcodes.OPC_ishl:
8074: case Opcodes.OPC_lshl:
8075: case Opcodes.OPC_ishr:
8076: case Opcodes.OPC_lshr:
8077: case Opcodes.OPC_iushr:
8078: case Opcodes.OPC_lushr:
8079: case Opcodes.OPC_iand:
8080: case Opcodes.OPC_land:
8081: case Opcodes.OPC_ior:
8082: case Opcodes.OPC_lor:
8083: case Opcodes.OPC_ixor:
8084: case Opcodes.OPC_lxor:
8085: frame.numberOfStackItems--;
8086: pc++;
8087: break;
8088: case Opcodes.OPC_ineg:
8089: case Opcodes.OPC_lneg:
8090: case Opcodes.OPC_fneg:
8091: case Opcodes.OPC_dneg:
8092: pc++;
8093: break;
8094: case Opcodes.OPC_iinc:
8095: pc += 3;
8096: break;
8097: case Opcodes.OPC_i2l:
8098: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8099: TypeBinding.LONG);
8100: pc++;
8101: break;
8102: case Opcodes.OPC_i2f:
8103: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8104: TypeBinding.FLOAT);
8105: pc++;
8106: break;
8107: case Opcodes.OPC_i2d:
8108: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8109: TypeBinding.DOUBLE);
8110: pc++;
8111: break;
8112: case Opcodes.OPC_l2i:
8113: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8114: TypeBinding.INT);
8115: pc++;
8116: break;
8117: case Opcodes.OPC_l2f:
8118: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8119: TypeBinding.FLOAT);
8120: pc++;
8121: break;
8122: case Opcodes.OPC_l2d:
8123: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8124: TypeBinding.DOUBLE);
8125: pc++;
8126: break;
8127: case Opcodes.OPC_f2i:
8128: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8129: TypeBinding.INT);
8130: pc++;
8131: break;
8132: case Opcodes.OPC_f2l:
8133: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8134: TypeBinding.LONG);
8135: pc++;
8136: break;
8137: case Opcodes.OPC_f2d:
8138: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8139: TypeBinding.DOUBLE);
8140: pc++;
8141: break;
8142: case Opcodes.OPC_d2i:
8143: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8144: TypeBinding.INT);
8145: pc++;
8146: break;
8147: case Opcodes.OPC_d2l:
8148: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8149: TypeBinding.LONG);
8150: pc++;
8151: break;
8152: case Opcodes.OPC_d2f:
8153: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8154: TypeBinding.FLOAT);
8155: pc++;
8156: break;
8157: case Opcodes.OPC_i2b:
8158: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8159: TypeBinding.BYTE);
8160: pc++;
8161: break;
8162: case Opcodes.OPC_i2c:
8163: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8164: TypeBinding.CHAR);
8165: pc++;
8166: break;
8167: case Opcodes.OPC_i2s:
8168: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8169: TypeBinding.SHORT);
8170: pc++;
8171: break;
8172: case Opcodes.OPC_lcmp:
8173: case Opcodes.OPC_fcmpl:
8174: case Opcodes.OPC_fcmpg:
8175: case Opcodes.OPC_dcmpl:
8176: case Opcodes.OPC_dcmpg:
8177: frame.numberOfStackItems -= 2;
8178: frame.addStackItem(TypeBinding.INT);
8179: pc++;
8180: break;
8181: case Opcodes.OPC_ifeq:
8182: case Opcodes.OPC_ifne:
8183: case Opcodes.OPC_iflt:
8184: case Opcodes.OPC_ifge:
8185: case Opcodes.OPC_ifgt:
8186: case Opcodes.OPC_ifle:
8187: frame.numberOfStackItems--;
8188: pc += 3;
8189: break;
8190: case Opcodes.OPC_if_icmpeq:
8191: case Opcodes.OPC_if_icmpne:
8192: case Opcodes.OPC_if_icmplt:
8193: case Opcodes.OPC_if_icmpge:
8194: case Opcodes.OPC_if_icmpgt:
8195: case Opcodes.OPC_if_icmple:
8196: case Opcodes.OPC_if_acmpeq:
8197: case Opcodes.OPC_if_acmpne:
8198: frame.numberOfStackItems -= 2;
8199: pc += 3;
8200: break;
8201: case Opcodes.OPC_goto:
8202: pc += 3;
8203: break;
8204: case Opcodes.OPC_tableswitch:
8205: pc++;
8206: while (((pc - codeOffset) & 0x03) != 0) {
8207: pc++;
8208: }
8209: pc += 4; // default
8210: int low = i4At(bytecodes, 0, pc);
8211: pc += 4;
8212: int high = i4At(bytecodes, 0, pc);
8213: pc += 4;
8214: int length = high - low + 1;
8215: pc += (length * 4);
8216: frame.numberOfStackItems--;
8217: break;
8218: case Opcodes.OPC_lookupswitch:
8219: pc++;
8220: while (((pc - codeOffset) & 0x03) != 0) {
8221: pc++;
8222: }
8223: pc += 4; // default
8224: int npairs = (int) u4At(bytecodes, 0, pc);
8225: pc += (4 + npairs * 8);
8226: frame.numberOfStackItems--;
8227: break;
8228: case Opcodes.OPC_ireturn:
8229: case Opcodes.OPC_lreturn:
8230: case Opcodes.OPC_freturn:
8231: case Opcodes.OPC_dreturn:
8232: case Opcodes.OPC_areturn:
8233: frame.numberOfStackItems--;
8234: pc++;
8235: break;
8236: case Opcodes.OPC_return:
8237: pc++;
8238: break;
8239: case Opcodes.OPC_getstatic:
8240: index = u2At(bytecodes, 1, pc);
8241: int nameAndTypeIndex = u2At(poolContents, 3,
8242: constantPoolOffsets[index]);
8243: int utf8index = u2At(poolContents, 3,
8244: constantPoolOffsets[nameAndTypeIndex]);
8245: char[] descriptor = utf8At(poolContents,
8246: constantPoolOffsets[utf8index] + 3, u2At(
8247: poolContents, 1,
8248: constantPoolOffsets[utf8index]));
8249: if (descriptor.length == 1) {
8250: // base type
8251: switch (descriptor[0]) {
8252: case 'Z':
8253: frame.addStackItem(TypeBinding.BOOLEAN);
8254: break;
8255: case 'B':
8256: frame.addStackItem(TypeBinding.BYTE);
8257: break;
8258: case 'C':
8259: frame.addStackItem(TypeBinding.CHAR);
8260: break;
8261: case 'D':
8262: frame.addStackItem(TypeBinding.DOUBLE);
8263: break;
8264: case 'F':
8265: frame.addStackItem(TypeBinding.FLOAT);
8266: break;
8267: case 'I':
8268: frame.addStackItem(TypeBinding.INT);
8269: break;
8270: case 'J':
8271: frame.addStackItem(TypeBinding.LONG);
8272: break;
8273: case 'S':
8274: frame.addStackItem(TypeBinding.SHORT);
8275: break;
8276: }
8277: } else if (descriptor[0] == '[') {
8278: frame.addStackItem(new VerificationTypeInfo(0,
8279: descriptor));
8280: } else {
8281: frame.addStackItem(new VerificationTypeInfo(0,
8282: CharOperation.subarray(descriptor, 1,
8283: descriptor.length - 1)));
8284: }
8285: pc += 3;
8286: break;
8287: case Opcodes.OPC_putstatic:
8288: frame.numberOfStackItems--;
8289: pc += 3;
8290: break;
8291: case Opcodes.OPC_getfield:
8292: index = u2At(bytecodes, 1, pc);
8293: nameAndTypeIndex = u2At(poolContents, 3,
8294: constantPoolOffsets[index]);
8295: utf8index = u2At(poolContents, 3,
8296: constantPoolOffsets[nameAndTypeIndex]);
8297: descriptor = utf8At(poolContents,
8298: constantPoolOffsets[utf8index] + 3, u2At(
8299: poolContents, 1,
8300: constantPoolOffsets[utf8index]));
8301: frame.numberOfStackItems--;
8302: if (descriptor.length == 1) {
8303: // base type
8304: switch (descriptor[0]) {
8305: case 'Z':
8306: frame.addStackItem(TypeBinding.BOOLEAN);
8307: break;
8308: case 'B':
8309: frame.addStackItem(TypeBinding.BYTE);
8310: break;
8311: case 'C':
8312: frame.addStackItem(TypeBinding.CHAR);
8313: break;
8314: case 'D':
8315: frame.addStackItem(TypeBinding.DOUBLE);
8316: break;
8317: case 'F':
8318: frame.addStackItem(TypeBinding.FLOAT);
8319: break;
8320: case 'I':
8321: frame.addStackItem(TypeBinding.INT);
8322: break;
8323: case 'J':
8324: frame.addStackItem(TypeBinding.LONG);
8325: break;
8326: case 'S':
8327: frame.addStackItem(TypeBinding.SHORT);
8328: break;
8329: }
8330: } else if (descriptor[0] == '[') {
8331: frame.addStackItem(new VerificationTypeInfo(0,
8332: descriptor));
8333: } else {
8334: frame.addStackItem(new VerificationTypeInfo(0,
8335: CharOperation.subarray(descriptor, 1,
8336: descriptor.length - 1)));
8337: }
8338: pc += 3;
8339: break;
8340: case Opcodes.OPC_putfield:
8341: frame.numberOfStackItems -= 2;
8342: pc += 3;
8343: break;
8344: case Opcodes.OPC_invokevirtual:
8345: index = u2At(bytecodes, 1, pc);
8346: nameAndTypeIndex = u2At(poolContents, 3,
8347: constantPoolOffsets[index]);
8348: utf8index = u2At(poolContents, 3,
8349: constantPoolOffsets[nameAndTypeIndex]);
8350: descriptor = utf8At(poolContents,
8351: constantPoolOffsets[utf8index] + 3, u2At(
8352: poolContents, 1,
8353: constantPoolOffsets[utf8index]));
8354: utf8index = u2At(poolContents, 1,
8355: constantPoolOffsets[nameAndTypeIndex]);
8356: char[] name = utf8At(poolContents,
8357: constantPoolOffsets[utf8index] + 3, u2At(
8358: poolContents, 1,
8359: constantPoolOffsets[utf8index]));
8360: frame.numberOfStackItems -= (getParametersCount(descriptor) + 1);
8361: char[] returnType = getReturnType(descriptor);
8362: if (returnType.length == 1) {
8363: // base type
8364: switch (returnType[0]) {
8365: case 'Z':
8366: frame.addStackItem(TypeBinding.BOOLEAN);
8367: break;
8368: case 'B':
8369: frame.addStackItem(TypeBinding.BYTE);
8370: break;
8371: case 'C':
8372: frame.addStackItem(TypeBinding.CHAR);
8373: break;
8374: case 'D':
8375: frame.addStackItem(TypeBinding.DOUBLE);
8376: break;
8377: case 'F':
8378: frame.addStackItem(TypeBinding.FLOAT);
8379: break;
8380: case 'I':
8381: frame.addStackItem(TypeBinding.INT);
8382: break;
8383: case 'J':
8384: frame.addStackItem(TypeBinding.LONG);
8385: break;
8386: case 'S':
8387: frame.addStackItem(TypeBinding.SHORT);
8388: break;
8389: }
8390: } else {
8391: if (returnType[0] == '[') {
8392: frame.addStackItem(new VerificationTypeInfo(0,
8393: returnType));
8394: } else {
8395: frame.addStackItem(new VerificationTypeInfo(0,
8396: CharOperation.subarray(returnType, 1,
8397: returnType.length - 1)));
8398: }
8399: }
8400: pc += 3;
8401: break;
8402: case Opcodes.OPC_invokespecial:
8403: index = u2At(bytecodes, 1, pc);
8404: nameAndTypeIndex = u2At(poolContents, 3,
8405: constantPoolOffsets[index]);
8406: utf8index = u2At(poolContents, 3,
8407: constantPoolOffsets[nameAndTypeIndex]);
8408: descriptor = utf8At(poolContents,
8409: constantPoolOffsets[utf8index] + 3, u2At(
8410: poolContents, 1,
8411: constantPoolOffsets[utf8index]));
8412: utf8index = u2At(poolContents, 1,
8413: constantPoolOffsets[nameAndTypeIndex]);
8414: name = utf8At(poolContents,
8415: constantPoolOffsets[utf8index] + 3, u2At(
8416: poolContents, 1,
8417: constantPoolOffsets[utf8index]));
8418: frame.numberOfStackItems -= getParametersCount(descriptor);
8419: if (CharOperation.equals(ConstantPool.Init, name)) {
8420: // constructor
8421: frame.stackItems[frame.numberOfStackItems - 1].tag = VerificationTypeInfo.ITEM_OBJECT;
8422: }
8423: frame.numberOfStackItems--;
8424: returnType = getReturnType(descriptor);
8425: if (returnType.length == 1) {
8426: // base type
8427: switch (returnType[0]) {
8428: case 'Z':
8429: frame.addStackItem(TypeBinding.BOOLEAN);
8430: break;
8431: case 'B':
8432: frame.addStackItem(TypeBinding.BYTE);
8433: break;
8434: case 'C':
8435: frame.addStackItem(TypeBinding.CHAR);
8436: break;
8437: case 'D':
8438: frame.addStackItem(TypeBinding.DOUBLE);
8439: break;
8440: case 'F':
8441: frame.addStackItem(TypeBinding.FLOAT);
8442: break;
8443: case 'I':
8444: frame.addStackItem(TypeBinding.INT);
8445: break;
8446: case 'J':
8447: frame.addStackItem(TypeBinding.LONG);
8448: break;
8449: case 'S':
8450: frame.addStackItem(TypeBinding.SHORT);
8451: break;
8452: }
8453: } else {
8454: if (returnType[0] == '[') {
8455: frame.addStackItem(new VerificationTypeInfo(0,
8456: returnType));
8457: } else {
8458: frame.addStackItem(new VerificationTypeInfo(0,
8459: CharOperation.subarray(returnType, 1,
8460: returnType.length - 1)));
8461: }
8462: }
8463: pc += 3;
8464: break;
8465: case Opcodes.OPC_invokestatic:
8466: index = u2At(bytecodes, 1, pc);
8467: nameAndTypeIndex = u2At(poolContents, 3,
8468: constantPoolOffsets[index]);
8469: utf8index = u2At(poolContents, 3,
8470: constantPoolOffsets[nameAndTypeIndex]);
8471: descriptor = utf8At(poolContents,
8472: constantPoolOffsets[utf8index] + 3, u2At(
8473: poolContents, 1,
8474: constantPoolOffsets[utf8index]));
8475: utf8index = u2At(poolContents, 1,
8476: constantPoolOffsets[nameAndTypeIndex]);
8477: name = utf8At(poolContents,
8478: constantPoolOffsets[utf8index] + 3, u2At(
8479: poolContents, 1,
8480: constantPoolOffsets[utf8index]));
8481: frame.numberOfStackItems -= getParametersCount(descriptor);
8482: returnType = getReturnType(descriptor);
8483: if (returnType.length == 1) {
8484: // base type
8485: switch (returnType[0]) {
8486: case 'Z':
8487: frame.addStackItem(TypeBinding.BOOLEAN);
8488: break;
8489: case 'B':
8490: frame.addStackItem(TypeBinding.BYTE);
8491: break;
8492: case 'C':
8493: frame.addStackItem(TypeBinding.CHAR);
8494: break;
8495: case 'D':
8496: frame.addStackItem(TypeBinding.DOUBLE);
8497: break;
8498: case 'F':
8499: frame.addStackItem(TypeBinding.FLOAT);
8500: break;
8501: case 'I':
8502: frame.addStackItem(TypeBinding.INT);
8503: break;
8504: case 'J':
8505: frame.addStackItem(TypeBinding.LONG);
8506: break;
8507: case 'S':
8508: frame.addStackItem(TypeBinding.SHORT);
8509: break;
8510: }
8511: } else {
8512: if (returnType[0] == '[') {
8513: frame.addStackItem(new VerificationTypeInfo(0,
8514: returnType));
8515: } else {
8516: frame.addStackItem(new VerificationTypeInfo(0,
8517: CharOperation.subarray(returnType, 1,
8518: returnType.length - 1)));
8519: }
8520: }
8521: pc += 3;
8522: break;
8523: case Opcodes.OPC_invokeinterface:
8524: index = u2At(bytecodes, 1, pc);
8525: nameAndTypeIndex = u2At(poolContents, 3,
8526: constantPoolOffsets[index]);
8527: utf8index = u2At(poolContents, 3,
8528: constantPoolOffsets[nameAndTypeIndex]);
8529: descriptor = utf8At(poolContents,
8530: constantPoolOffsets[utf8index] + 3, u2At(
8531: poolContents, 1,
8532: constantPoolOffsets[utf8index]));
8533: utf8index = u2At(poolContents, 1,
8534: constantPoolOffsets[nameAndTypeIndex]);
8535: name = utf8At(poolContents,
8536: constantPoolOffsets[utf8index] + 3, u2At(
8537: poolContents, 1,
8538: constantPoolOffsets[utf8index]));
8539: // we don't need count and args
8540: // u1At(bytecodes, 3, pc); // count
8541: // u1At(bytecodes, 4, pc); // extra args
8542: frame.numberOfStackItems -= (getParametersCount(descriptor) + 1);
8543: returnType = getReturnType(descriptor);
8544: if (returnType.length == 1) {
8545: // base type
8546: switch (returnType[0]) {
8547: case 'Z':
8548: frame.addStackItem(TypeBinding.BOOLEAN);
8549: break;
8550: case 'B':
8551: frame.addStackItem(TypeBinding.BYTE);
8552: break;
8553: case 'C':
8554: frame.addStackItem(TypeBinding.CHAR);
8555: break;
8556: case 'D':
8557: frame.addStackItem(TypeBinding.DOUBLE);
8558: break;
8559: case 'F':
8560: frame.addStackItem(TypeBinding.FLOAT);
8561: break;
8562: case 'I':
8563: frame.addStackItem(TypeBinding.INT);
8564: break;
8565: case 'J':
8566: frame.addStackItem(TypeBinding.LONG);
8567: break;
8568: case 'S':
8569: frame.addStackItem(TypeBinding.SHORT);
8570: break;
8571: }
8572: } else {
8573: if (returnType[0] == '[') {
8574: frame.addStackItem(new VerificationTypeInfo(0,
8575: returnType));
8576: } else {
8577: frame.addStackItem(new VerificationTypeInfo(0,
8578: CharOperation.subarray(returnType, 1,
8579: returnType.length - 1)));
8580: }
8581: }
8582: pc += 5;
8583: break;
8584: case Opcodes.OPC_new:
8585: index = u2At(bytecodes, 1, pc);
8586: utf8index = u2At(poolContents, 1,
8587: constantPoolOffsets[index]);
8588: char[] className = utf8At(poolContents,
8589: constantPoolOffsets[utf8index] + 3, u2At(
8590: poolContents, 1,
8591: constantPoolOffsets[utf8index]));
8592: VerificationTypeInfo verificationTypeInfo = new VerificationTypeInfo(
8593: 0, VerificationTypeInfo.ITEM_UNINITIALIZED,
8594: className);
8595: verificationTypeInfo.offset = currentPC;
8596: frame.addStackItem(verificationTypeInfo);
8597: pc += 3;
8598: break;
8599: case Opcodes.OPC_newarray:
8600: char[] constantPoolName = null;
8601: switch (u1At(bytecodes, 1, pc)) {
8602: case ClassFileConstants.INT_ARRAY:
8603: constantPoolName = new char[] { '[', 'I' };
8604: break;
8605: case ClassFileConstants.BYTE_ARRAY:
8606: constantPoolName = new char[] { '[', 'B' };
8607: break;
8608: case ClassFileConstants.BOOLEAN_ARRAY:
8609: constantPoolName = new char[] { '[', 'Z' };
8610: break;
8611: case ClassFileConstants.SHORT_ARRAY:
8612: constantPoolName = new char[] { '[', 'S' };
8613: break;
8614: case ClassFileConstants.CHAR_ARRAY:
8615: constantPoolName = new char[] { '[', 'C' };
8616: break;
8617: case ClassFileConstants.LONG_ARRAY:
8618: constantPoolName = new char[] { '[', 'J' };
8619: break;
8620: case ClassFileConstants.FLOAT_ARRAY:
8621: constantPoolName = new char[] { '[', 'F' };
8622: break;
8623: case ClassFileConstants.DOUBLE_ARRAY:
8624: constantPoolName = new char[] { '[', 'D' };
8625: break;
8626: }
8627: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8628: TypeIds.T_JavaLangObject, constantPoolName);
8629: pc += 2;
8630: break;
8631: case Opcodes.OPC_anewarray:
8632: index = u2At(bytecodes, 1, pc);
8633: utf8index = u2At(poolContents, 1,
8634: constantPoolOffsets[index]);
8635: className = utf8At(poolContents,
8636: constantPoolOffsets[utf8index] + 3, u2At(
8637: poolContents, 1,
8638: constantPoolOffsets[utf8index]));
8639: int classNameLength = className.length;
8640: System
8641: .arraycopy(
8642: className,
8643: 0,
8644: (constantPoolName = new char[classNameLength + 3]),
8645: 2, classNameLength);
8646: constantPoolName[0] = '[';
8647: constantPoolName[1] = 'L';
8648: constantPoolName[classNameLength + 2] = ';';
8649: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8650: 0, constantPoolName);
8651: pc += 3;
8652: break;
8653: case Opcodes.OPC_arraylength:
8654: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8655: TypeBinding.INT);
8656: pc++;
8657: break;
8658: case Opcodes.OPC_athrow:
8659: frame.numberOfStackItems--;
8660: pc++;
8661: break;
8662: case Opcodes.OPC_checkcast:
8663: index = u2At(bytecodes, 1, pc);
8664: utf8index = u2At(poolContents, 1,
8665: constantPoolOffsets[index]);
8666: className = utf8At(poolContents,
8667: constantPoolOffsets[utf8index] + 3, u2At(
8668: poolContents, 1,
8669: constantPoolOffsets[utf8index]));
8670: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8671: 0, className);
8672: pc += 3;
8673: break;
8674: case Opcodes.OPC_instanceof :
8675: // no need to know the class index = u2At(bytecodes, 1, pc);
8676: frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(
8677: TypeBinding.INT);
8678: pc += 3;
8679: break;
8680: case Opcodes.OPC_monitorenter:
8681: case Opcodes.OPC_monitorexit:
8682: frame.numberOfStackItems--;
8683: pc++;
8684: break;
8685: case Opcodes.OPC_wide:
8686: opcode = (byte) u1At(bytecodes, 1, pc);
8687: if (opcode == Opcodes.OPC_iinc) {
8688: // index = u2At(bytecodes, 2, pc);
8689: // i2At(bytecodes, 4, pc); // const
8690: // we don't need the index and the const value
8691: pc += 6;
8692: } else {
8693: index = u2At(bytecodes, 2, pc);
8694: // need to handle iload, fload, aload, lload, dload, istore, fstore, astore, lstore or dstore
8695: switch (opcode) {
8696: case Opcodes.OPC_iload:
8697: frame.addStackItem(TypeBinding.INT);
8698: break;
8699: case Opcodes.OPC_fload:
8700: frame.addStackItem(TypeBinding.FLOAT);
8701: break;
8702: case Opcodes.OPC_aload:
8703: localsN = frame.locals[index];
8704: if (localsN == null) {
8705: localsN = retrieveLocal(currentPC, index);
8706: }
8707: frame.addStackItem(localsN);
8708: break;
8709: case Opcodes.OPC_lload:
8710: frame.addStackItem(TypeBinding.LONG);
8711: break;
8712: case Opcodes.OPC_dload:
8713: frame.addStackItem(TypeBinding.DOUBLE);
8714: break;
8715: case Opcodes.OPC_istore:
8716: frame.numberOfStackItems--;
8717: break;
8718: case Opcodes.OPC_fstore:
8719: frame.numberOfStackItems--;
8720: break;
8721: case Opcodes.OPC_astore:
8722: frame.locals[index] = frame.stackItems[frame.numberOfStackItems - 1];
8723: frame.numberOfStackItems--;
8724: break;
8725: case Opcodes.OPC_lstore:
8726: frame.numberOfStackItems--;
8727: break;
8728: case Opcodes.OPC_dstore:
8729: frame.numberOfStackItems--;
8730: break;
8731: }
8732: pc += 4;
8733: }
8734: break;
8735: case Opcodes.OPC_multianewarray:
8736: index = u2At(bytecodes, 1, pc);
8737: utf8index = u2At(poolContents, 1,
8738: constantPoolOffsets[index]);
8739: className = utf8At(poolContents,
8740: constantPoolOffsets[utf8index] + 3, u2At(
8741: poolContents, 1,
8742: constantPoolOffsets[utf8index]));
8743: int dimensions = u1At(bytecodes, 3, pc); // dimensions
8744: frame.numberOfStackItems -= dimensions;
8745: classNameLength = className.length;
8746: constantPoolName = new char[classNameLength
8747: + dimensions];
8748: for (int i = 0; i < dimensions; i++) {
8749: constantPoolName[i] = '[';
8750: }
8751: System.arraycopy(className, 0, constantPoolName,
8752: dimensions, classNameLength);
8753: frame.addStackItem(new VerificationTypeInfo(0,
8754: constantPoolName));
8755: pc += 4;
8756: break;
8757: case Opcodes.OPC_ifnull:
8758: case Opcodes.OPC_ifnonnull:
8759: frame.numberOfStackItems--;
8760: pc += 3;
8761: break;
8762: case Opcodes.OPC_goto_w:
8763: pc += 5;
8764: break;
8765: default: // should not occur
8766: codeStream.methodDeclaration.scope
8767: .problemReporter()
8768: .abortDueToInternalError(
8769: Messages
8770: .bind(
8771: Messages.abort_invalidOpcode,
8772: new Object[] {
8773: new Byte(opcode),
8774: new Integer(pc),
8775: new String(
8776: methodBinding
8777: .shortReadableName()), }),
8778: codeStream.methodDeclaration);
8779: break;
8780: }
8781: if (pc >= (codeLength + codeOffset)) {
8782: break;
8783: }
8784: }
8785: }
8786:
8787: private void initializeDefaultLocals(StackMapFrame frame,
8788: MethodBinding methodBinding, int maxLocals, int codeLength) {
8789: if (maxLocals != 0) {
8790: int resolvedPosition = 0;
8791: // take into account enum constructor synthetic name+ordinal
8792: final boolean isConstructor = methodBinding.isConstructor();
8793: if (isConstructor) {
8794: LocalVariableBinding localVariableBinding = new LocalVariableBinding(
8795: "this".toCharArray(), methodBinding.declaringClass, 0, false); //$NON-NLS-1$
8796: localVariableBinding.resolvedPosition = 0;
8797: codeStream.record(localVariableBinding);
8798: localVariableBinding.recordInitializationStartPC(0);
8799: localVariableBinding
8800: .recordInitializationEndPC(codeLength);
8801: frame
8802: .putLocal(
8803: resolvedPosition,
8804: new VerificationTypeInfo(
8805: VerificationTypeInfo.ITEM_UNINITIALIZED_THIS,
8806: methodBinding.declaringClass));
8807: resolvedPosition++;
8808: } else if (!methodBinding.isStatic()) {
8809: LocalVariableBinding localVariableBinding = new LocalVariableBinding(
8810: "this".toCharArray(), methodBinding.declaringClass, 0, false); //$NON-NLS-1$
8811: localVariableBinding.resolvedPosition = 0;
8812: codeStream.record(localVariableBinding);
8813: localVariableBinding.recordInitializationStartPC(0);
8814: localVariableBinding
8815: .recordInitializationEndPC(codeLength);
8816: frame.putLocal(resolvedPosition,
8817: new VerificationTypeInfo(
8818: VerificationTypeInfo.ITEM_OBJECT,
8819: methodBinding.declaringClass));
8820: resolvedPosition++;
8821: }
8822:
8823: if (isConstructor) {
8824: if (methodBinding.declaringClass.isEnum()) {
8825: LocalVariableBinding localVariableBinding = new LocalVariableBinding(
8826: " name".toCharArray(), this .referenceBinding.scope.getJavaLangString(), 0, false); //$NON-NLS-1$
8827: localVariableBinding.resolvedPosition = resolvedPosition;
8828: codeStream.record(localVariableBinding);
8829: localVariableBinding.recordInitializationStartPC(0);
8830: localVariableBinding
8831: .recordInitializationEndPC(codeLength);
8832:
8833: frame
8834: .putLocal(
8835: resolvedPosition,
8836: new VerificationTypeInfo(
8837: TypeIds.T_JavaLangString,
8838: ConstantPool.JavaLangStringConstantPoolName));
8839: resolvedPosition++;
8840:
8841: localVariableBinding = new LocalVariableBinding(
8842: " ordinal".toCharArray(), TypeBinding.INT, 0, false); //$NON-NLS-1$
8843: localVariableBinding.resolvedPosition = resolvedPosition;
8844: codeStream.record(localVariableBinding);
8845: localVariableBinding.recordInitializationStartPC(0);
8846: localVariableBinding
8847: .recordInitializationEndPC(codeLength);
8848: frame.putLocal(resolvedPosition,
8849: new VerificationTypeInfo(TypeBinding.INT));
8850: resolvedPosition++;
8851: }
8852:
8853: // take into account the synthetic parameters
8854: if (methodBinding.declaringClass.isNestedType()) {
8855: ReferenceBinding enclosingInstanceTypes[];
8856: if ((enclosingInstanceTypes = methodBinding.declaringClass
8857: .syntheticEnclosingInstanceTypes()) != null) {
8858: for (int i = 0, max = enclosingInstanceTypes.length; i < max; i++) {
8859: // an enclosingInstanceType can only be a reference
8860: // binding. It cannot be
8861: // LongBinding or DoubleBinding
8862: LocalVariableBinding localVariableBinding = new LocalVariableBinding(
8863: (" enclosingType" + i).toCharArray(), enclosingInstanceTypes[i], 0, false); //$NON-NLS-1$
8864: localVariableBinding.resolvedPosition = resolvedPosition;
8865: codeStream.record(localVariableBinding);
8866: localVariableBinding
8867: .recordInitializationStartPC(0);
8868: localVariableBinding
8869: .recordInitializationEndPC(codeLength);
8870:
8871: frame.putLocal(resolvedPosition,
8872: new VerificationTypeInfo(
8873: enclosingInstanceTypes[i]));
8874: resolvedPosition++;
8875: }
8876: }
8877:
8878: TypeBinding[] arguments;
8879: if ((arguments = methodBinding.parameters) != null) {
8880: for (int i = 0, max = arguments.length; i < max; i++) {
8881: final TypeBinding typeBinding = arguments[i];
8882: frame.putLocal(resolvedPosition,
8883: new VerificationTypeInfo(
8884: typeBinding));
8885: switch (typeBinding.id) {
8886: case TypeIds.T_double:
8887: case TypeIds.T_long:
8888: resolvedPosition += 2;
8889: break;
8890: default:
8891: resolvedPosition++;
8892: }
8893: }
8894: }
8895:
8896: SyntheticArgumentBinding syntheticArguments[];
8897: if ((syntheticArguments = methodBinding.declaringClass
8898: .syntheticOuterLocalVariables()) != null) {
8899: for (int i = 0, max = syntheticArguments.length; i < max; i++) {
8900: final TypeBinding typeBinding = syntheticArguments[i].type;
8901: LocalVariableBinding localVariableBinding = new LocalVariableBinding(
8902: (" synthetic" + i).toCharArray(), typeBinding, 0, false); //$NON-NLS-1$
8903: localVariableBinding.resolvedPosition = resolvedPosition;
8904: codeStream.record(localVariableBinding);
8905: localVariableBinding
8906: .recordInitializationStartPC(0);
8907: localVariableBinding
8908: .recordInitializationEndPC(codeLength);
8909:
8910: frame.putLocal(resolvedPosition,
8911: new VerificationTypeInfo(
8912: typeBinding));
8913: switch (typeBinding.id) {
8914: case TypeIds.T_double:
8915: case TypeIds.T_long:
8916: resolvedPosition += 2;
8917: break;
8918: default:
8919: resolvedPosition++;
8920: }
8921: }
8922: }
8923: } else {
8924: TypeBinding[] arguments;
8925: if ((arguments = methodBinding.parameters) != null) {
8926: for (int i = 0, max = arguments.length; i < max; i++) {
8927: final TypeBinding typeBinding = arguments[i];
8928: frame.putLocal(resolvedPosition,
8929: new VerificationTypeInfo(
8930: typeBinding));
8931: switch (typeBinding.id) {
8932: case TypeIds.T_double:
8933: case TypeIds.T_long:
8934: resolvedPosition += 2;
8935: break;
8936: default:
8937: resolvedPosition++;
8938: }
8939: }
8940: }
8941: }
8942: } else {
8943: TypeBinding[] arguments;
8944: if ((arguments = methodBinding.parameters) != null) {
8945: for (int i = 0, max = arguments.length; i < max; i++) {
8946: final TypeBinding typeBinding = arguments[i];
8947: frame.putLocal(resolvedPosition,
8948: new VerificationTypeInfo(typeBinding));
8949: switch (typeBinding.id) {
8950: case TypeIds.T_double:
8951: case TypeIds.T_long:
8952: resolvedPosition += 2;
8953: break;
8954: default:
8955: resolvedPosition++;
8956: }
8957: }
8958: }
8959: }
8960: }
8961: }
8962:
8963: private void initializeLocals(boolean isStatic, int currentPC,
8964: StackMapFrame currentFrame) {
8965: VerificationTypeInfo[] locals = currentFrame.locals;
8966: int localsLength = locals.length;
8967: int i = 0;
8968: if (!isStatic) {
8969: // we don't want to reset the first local if the method is not static
8970: i = 1;
8971: }
8972: for (; i < localsLength; i++) {
8973: locals[i] = null;
8974: }
8975: i = 0;
8976: locals: for (int max = codeStream.allLocalsCounter; i < max; i++) {
8977: LocalVariableBinding localVariable = codeStream.locals[i];
8978: if (localVariable == null)
8979: continue;
8980: int resolvedPosition = localVariable.resolvedPosition;
8981: final TypeBinding localVariableTypeBinding = localVariable.type;
8982: inits: for (int j = 0; j < localVariable.initializationCount; j++) {
8983: int startPC = localVariable.initializationPCs[j << 1];
8984: int endPC = localVariable.initializationPCs[(j << 1) + 1];
8985: if (currentPC < startPC) {
8986: continue inits;
8987: } else if (currentPC < endPC) {
8988: // the current local is an active local
8989: if (currentFrame.locals[resolvedPosition] == null) {
8990: currentFrame.locals[resolvedPosition] = new VerificationTypeInfo(
8991: localVariableTypeBinding);
8992: }
8993: continue locals;
8994: }
8995: }
8996: }
8997: }
8998:
8999: private VerificationTypeInfo retrieveLocal(int currentPC,
9000: int resolvedPosition) {
9001: for (int i = 0, max = codeStream.allLocalsCounter; i < max; i++) {
9002: LocalVariableBinding localVariable = codeStream.locals[i];
9003: if (localVariable == null)
9004: continue;
9005: if (resolvedPosition == localVariable.resolvedPosition) {
9006: inits: for (int j = 0; j < localVariable.initializationCount; j++) {
9007: int startPC = localVariable.initializationPCs[j << 1];
9008: int endPC = localVariable.initializationPCs[(j << 1) + 1];
9009: if (currentPC < startPC) {
9010: continue inits;
9011: } else if (currentPC < endPC) {
9012: // the current local is an active local
9013: return new VerificationTypeInfo(
9014: localVariable.type);
9015: }
9016: }
9017: }
9018: }
9019: return null;
9020: }
9021:
9022: private final int u1At(byte[] reference, int relativeOffset,
9023: int structOffset) {
9024: return (reference[relativeOffset + structOffset] & 0xFF);
9025: }
9026:
9027: private final int i4At(byte[] reference, int relativeOffset,
9028: int structOffset) {
9029: int position = relativeOffset + structOffset;
9030: return ((reference[position++] & 0xFF) << 24)
9031: + ((reference[position++] & 0xFF) << 16)
9032: + ((reference[position++] & 0xFF) << 8)
9033: + (reference[position] & 0xFF);
9034: }
9035:
9036: private final int u2At(byte[] reference, int relativeOffset,
9037: int structOffset) {
9038: int position = relativeOffset + structOffset;
9039: return ((reference[position++] & 0xFF) << 8)
9040: + (reference[position] & 0xFF);
9041: }
9042:
9043: private final long u4At(byte[] reference, int relativeOffset,
9044: int structOffset) {
9045: int position = relativeOffset + structOffset;
9046: return (((reference[position++] & 0xFFL) << 24)
9047: + ((reference[position++] & 0xFF) << 16)
9048: + ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF));
9049: }
9050:
9051: public char[] utf8At(byte[] reference, int absoluteOffset,
9052: int bytesAvailable) {
9053: int length = bytesAvailable;
9054: char outputBuf[] = new char[bytesAvailable];
9055: int outputPos = 0;
9056: int readOffset = absoluteOffset;
9057:
9058: while (length != 0) {
9059: int x = reference[readOffset++] & 0xFF;
9060: length--;
9061: if ((0x80 & x) != 0) {
9062: if ((x & 0x20) != 0) {
9063: length -= 2;
9064: x = ((x & 0xF) << 12)
9065: | ((reference[readOffset++] & 0x3F) << 6)
9066: | (reference[readOffset++] & 0x3F);
9067: } else {
9068: length--;
9069: x = ((x & 0x1F) << 6)
9070: | (reference[readOffset++] & 0x3F);
9071: }
9072: }
9073: outputBuf[outputPos++] = (char) x;
9074: }
9075:
9076: if (outputPos != bytesAvailable) {
9077: System.arraycopy(outputBuf, 0,
9078: (outputBuf = new char[outputPos]), 0, outputPos);
9079: }
9080: return outputBuf;
9081: }
9082:
9083: private char[] getReturnType(char[] methodSignature) {
9084: // skip type parameters
9085: int paren = CharOperation.lastIndexOf(')', methodSignature);
9086: // there could be thrown exceptions behind, thus scan one type exactly
9087: return CharOperation.subarray(methodSignature, paren + 1,
9088: methodSignature.length);
9089: }
9090:
9091: private int getParametersCount(char[] methodSignature) {
9092: int i = CharOperation.indexOf('(', methodSignature);
9093: i++;
9094: char currentCharacter = methodSignature[i];
9095: if (currentCharacter == ')') {
9096: return 0;
9097: }
9098: int result = 0;
9099: while (true) {
9100: currentCharacter = methodSignature[i];
9101: if (currentCharacter == ')') {
9102: return result;
9103: }
9104: switch (currentCharacter) {
9105: case '[':
9106: // array type
9107: int scanType = scanType(methodSignature, i + 1);
9108: result++;
9109: i = scanType + 1;
9110: break;
9111: case 'L':
9112: scanType = CharOperation.indexOf(';', methodSignature,
9113: i + 1);
9114: result++;
9115: i = scanType + 1;
9116: break;
9117: case 'Z':
9118: case 'B':
9119: case 'C':
9120: case 'D':
9121: case 'F':
9122: case 'I':
9123: case 'J':
9124: case 'S':
9125: result++;
9126: i++;
9127: break;
9128: default:
9129: throw new IllegalArgumentException();
9130: }
9131: }
9132: }
9133:
9134: private int scanType(char[] methodSignature, int index) {
9135: switch (methodSignature[index]) {
9136: case '[':
9137: // array type
9138: return scanType(methodSignature, index + 1);
9139: case 'L':
9140: return CharOperation.indexOf(';', methodSignature,
9141: index + 1);
9142: case 'Z':
9143: case 'B':
9144: case 'C':
9145: case 'D':
9146: case 'F':
9147: case 'I':
9148: case 'J':
9149: case 'S':
9150: return index;
9151: default:
9152: throw new IllegalArgumentException();
9153: }
9154: }
9155: }
|