diff options
author | Andy Clement <aclement@pivotal.io> | 2018-10-11 10:58:44 -0700 |
---|---|---|
committer | Andy Clement <aclement@pivotal.io> | 2018-10-11 10:58:44 -0700 |
commit | ef7411136acfe9dd531d8e9faeb439025cd3c3c6 (patch) | |
tree | 2dc44938f6f3c6d6064636d3ff18db7fb4b6351f /org.eclipse.jdt.core | |
parent | a913ec7fb308c794bd53f33f1d5b7163d144cf23 (diff) | |
download | aspectj-ef7411136acfe9dd531d8e9faeb439025cd3c3c6.tar.gz aspectj-ef7411136acfe9dd531d8e9faeb439025cd3c3c6.zip |
Remove class used for debugging
Diffstat (limited to 'org.eclipse.jdt.core')
-rw-r--r-- | org.eclipse.jdt.core/src/org/aspectj/org/eclipse/jdt/internal/compiler/ClassFile.java | 6784 |
1 files changed, 0 insertions, 6784 deletions
diff --git a/org.eclipse.jdt.core/src/org/aspectj/org/eclipse/jdt/internal/compiler/ClassFile.java b/org.eclipse.jdt.core/src/org/aspectj/org/eclipse/jdt/internal/compiler/ClassFile.java deleted file mode 100644 index e3d1c415c..000000000 --- a/org.eclipse.jdt.core/src/org/aspectj/org/eclipse/jdt/internal/compiler/ClassFile.java +++ /dev/null @@ -1,6784 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2000, 2014 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - * Jesper S Moller - Contributions for - * Bug 405066 - [1.8][compiler][codegen] Implement code generation infrastructure for JSR335 - * Bug 406982 - [1.8][compiler] Generation of MethodParameters Attribute in classfile - * Bug 416885 - [1.8][compiler]IncompatibleClassChange error (edit) - * Bug 412149 - [1.8][compiler] Emit repeated annotations into the designated container - * Andy Clement (GoPivotal, Inc) aclement@gopivotal.com - Contributions for - * Bug 383624 - [1.8][compiler] Revive code generation support for type annotations (from Olivier's work) - * Bug 409236 - [1.8][compiler] Type annotations on intersection cast types dropped by code generator - * Bug 409246 - [1.8][compiler] Type annotations on catch parameters not handled properly - * Bug 415541 - [1.8][compiler] Type annotations in the body of static initializer get dropped - * Bug 415399 - [1.8][compiler] Type annotations on constructor results dropped by the code generator - * Bug 415470 - [1.8][compiler] Type annotations on class declaration go vanishing - * Bug 405104 - [1.8][compiler][codegen] Implement support for serializeable lambdas - * Bug 434556 - Broken class file generated for incorrect annotation usage - * Stephan Herrmann - Contribution for - * Bug 438458 - [1.8][null] clean up handling of null type annotations wrt type variables - *******************************************************************************/ -package org.aspectj.org.eclipse.jdt.internal.compiler; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.aspectj.org.eclipse.jdt.core.compiler.CategorizedProblem; -import org.aspectj.org.eclipse.jdt.core.compiler.CharOperation; -import org.aspectj.org.eclipse.jdt.core.compiler.IProblem; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ASTNode; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Annotation; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.AnnotationMethodDeclaration; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Argument; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Expression; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.FunctionalExpression; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.LambdaExpression; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MemberValuePair; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.MethodDeclaration; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.NormalAnnotation; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.Receiver; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.SingleNameReference; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeParameter; -import org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeReference; -import org.aspectj.org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.AnnotationContext; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.AnnotationTargetTypeConstants; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.AttributeNamesConstants; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.CodeStream; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.ConstantPool; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.ExceptionLabel; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.Opcodes; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.StackMapFrame; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.TypeAnnotationCodeStream; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.ExceptionMarker; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackDepthMarker; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.StackMapFrameCodeStream.StackMarker; -import org.aspectj.org.eclipse.jdt.internal.compiler.codegen.VerificationTypeInfo; -import org.aspectj.org.eclipse.jdt.internal.compiler.impl.CompilerOptions; -import org.aspectj.org.eclipse.jdt.internal.compiler.impl.Constant; -import org.aspectj.org.eclipse.jdt.internal.compiler.impl.StringConstant; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.Binding; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.FieldBinding; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.LookupEnvironment; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TagBits; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeBinding; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeConstants; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeIds; -import org.aspectj.org.eclipse.jdt.internal.compiler.lookup.TypeVariableBinding; -import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; -import org.aspectj.org.eclipse.jdt.internal.compiler.problem.ShouldNotImplement; -import org.aspectj.org.eclipse.jdt.internal.compiler.util.Messages; -import org.aspectj.org.eclipse.jdt.internal.compiler.util.Util; - -/** - * Represents a class file wrapper on bytes, it is aware of its actual - * type name. - * - * Public APIs are listed below: - * - * byte[] getBytes(); - * Answer the actual bytes of the class file - * - * char[][] getCompoundName(); - * Answer the compound name of the class file. - * For example, {{java}, {util}, {Hashtable}}. - * - * byte[] getReducedBytes(); - * Answer a smaller byte format, which is only contains some structural - * information. Those bytes are decodable with a regular class file reader, - * such as DietClassFileReader - */ -@SuppressWarnings({"rawtypes", "unchecked"}) -public class ClassFile implements TypeConstants, TypeIds { - - private byte[] bytes; - public CodeStream codeStream; - public ConstantPool constantPool; - - public int constantPoolOffset; - - // the header contains all the bytes till the end of the constant pool - public byte[] contents; - - public int contentsOffset; - - protected boolean creatingProblemType; - - public ClassFile enclosingClassFile; - public byte[] header; - // that collection contains all the remaining bytes of the .class file - public int headerOffset; - public Set innerClassesBindings; - public List bootstrapMethods = null; - public int methodCount; - public int methodCountOffset; - // pool managment - boolean isShared = false; - // used to generate private access methods - // debug and stack map attributes - public int produceAttributes; - public SourceTypeBinding referenceBinding; - public boolean isNestedType; - public long targetJDK; - - public List missingTypes = null; - - public Set visitedTypes; - - public static final int INITIAL_CONTENTS_SIZE = 400; - public static final int INITIAL_HEADER_SIZE = 1500; - public static final int INNER_CLASSES_SIZE = 5; - - /** - * INTERNAL USE-ONLY - * Request the creation of a ClassFile compatible representation of a problematic type - * - * @param typeDeclaration org.aspectj.org.eclipse.jdt.internal.compiler.ast.TypeDeclaration - * @param unitResult org.aspectj.org.eclipse.jdt.internal.compiler.CompilationUnitResult - */ - public static void createProblemType(TypeDeclaration typeDeclaration, CompilationResult unitResult) { - SourceTypeBinding typeBinding = typeDeclaration.binding; - ClassFile classFile = ClassFile.getNewInstance(typeBinding); - classFile.initialize(typeBinding, null, true); - - if (typeBinding.hasMemberTypes()) { - // see bug 180109 - ReferenceBinding[] members = typeBinding.memberTypes; - for (int i = 0, l = members.length; i < l; i++) - classFile.recordInnerClasses(members[i]); - } - // TODO (olivier) handle cases where a field cannot be generated (name too long) - // TODO (olivier) handle too many methods - // inner attributes - if (typeBinding.isNestedType()) { - classFile.recordInnerClasses(typeBinding); - } - TypeVariableBinding[] typeVariables = typeBinding.typeVariables(); - for (int i = 0, max = typeVariables.length; i < max; i++) { - TypeVariableBinding typeVariableBinding = typeVariables[i]; - if ((typeVariableBinding.tagBits & TagBits.ContainsNestedTypeReferences) != 0) { - Util.recordNestedType(classFile, typeVariableBinding); - } - } - // add its fields - FieldBinding[] fields = typeBinding.fields(); - if ((fields != null) && (fields != Binding.NO_FIELDS)) { - classFile.addFieldInfos(); - } else { - // we have to set the number of fields to be equals to 0 - classFile.contents[classFile.contentsOffset++] = 0; - classFile.contents[classFile.contentsOffset++] = 0; - } - // leave some space for the methodCount - classFile.setForMethodInfos(); - // add its user defined methods - int problemsLength; - CategorizedProblem[] problems = unitResult.getErrors(); - if (problems == null) { - problems = new CategorizedProblem[0]; - } - CategorizedProblem[] problemsCopy = new CategorizedProblem[problemsLength = problems.length]; - System.arraycopy(problems, 0, problemsCopy, 0, problemsLength); - - AbstractMethodDeclaration[] methodDecls = typeDeclaration.methods; - boolean abstractMethodsOnly = false; - if (methodDecls != null) { - if (typeBinding.isInterface()) { - if (typeBinding.scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_8) - abstractMethodsOnly = true; - // We generate a clinit which contains all the problems, since we may not be able to generate problem methods (< 1.8) and problem constructors (all levels). - classFile.addProblemClinit(problemsCopy); - } - for (int i = 0, length = methodDecls.length; i < length; i++) { - AbstractMethodDeclaration methodDecl = methodDecls[i]; - MethodBinding method = methodDecl.binding; - if (method == null) continue; - if (abstractMethodsOnly) { - method.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccAbstract; - } - if (method.isConstructor()) { - if (typeBinding.isInterface()) continue; - classFile.addProblemConstructor(methodDecl, method, problemsCopy); - } else if (method.isAbstract()) { - classFile.addAbstractMethod(methodDecl, method); - } else { - classFile.addProblemMethod(methodDecl, method, problemsCopy); - } - } - // add abstract methods - classFile.addDefaultAbstractMethods(); - } - - // propagate generation of (problem) member types - if (typeDeclaration.memberTypes != null) { - for (int i = 0, max = typeDeclaration.memberTypes.length; i < max; i++) { - TypeDeclaration memberType = typeDeclaration.memberTypes[i]; - if (memberType.binding != null) { - ClassFile.createProblemType(memberType, unitResult); - } - } - } - classFile.addAttributes(); - unitResult.record(typeBinding.constantPoolName(), classFile); - } - public static ClassFile getNewInstance(SourceTypeBinding typeBinding) { - LookupEnvironment env = typeBinding.scope.environment(); - return env.classFilePool.acquire(typeBinding); - } - /** - * INTERNAL USE-ONLY - * This methods creates a new instance of the receiver. - */ - protected ClassFile() { - // default constructor for subclasses - } - - public ClassFile(SourceTypeBinding typeBinding) { - // default constructor for subclasses - this.constantPool = new ConstantPool(this); - final CompilerOptions options = typeBinding.scope.compilerOptions(); - this.targetJDK = options.targetJDK; - this.produceAttributes = options.produceDebugAttributes; - this.referenceBinding = typeBinding; - this.isNestedType = typeBinding.isNestedType(); - if (this.targetJDK >= ClassFileConstants.JDK1_6) { - this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE; - if (this.targetJDK >= ClassFileConstants.JDK1_8) { - this.produceAttributes |= ClassFileConstants.ATTR_TYPE_ANNOTATION; - this.codeStream = new TypeAnnotationCodeStream(this); - if (options.produceMethodParameters) { - this.produceAttributes |= ClassFileConstants.ATTR_METHOD_PARAMETERS; - } - } else { - this.codeStream = new StackMapFrameCodeStream(this); - } - } else if (this.targetJDK == ClassFileConstants.CLDC_1_1) { - this.targetJDK = ClassFileConstants.JDK1_1; // put back 45.3 - this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP; - this.codeStream = new StackMapFrameCodeStream(this); - } else { - this.codeStream = new CodeStream(this); - } - initByteArrays(); - } - - /** - * INTERNAL USE-ONLY - * Generate the byte for a problem method info that correspond to a bogus method. - * - * @param method org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding - */ - public void addAbstractMethod( - AbstractMethodDeclaration method, - MethodBinding methodBinding) { - - this.generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - int attributeNumber = this.generateMethodInfoAttributes(methodBinding); - completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber); - } - - /** - * INTERNAL USE-ONLY - * This methods generate all the attributes for the receiver. - * For a class they could be: - * - source file attribute - * - inner classes attribute - * - deprecated attribute - */ - public void addAttributes() { - // update the method count - this.contents[this.methodCountOffset++] = (byte) (this.methodCount >> 8); - this.contents[this.methodCountOffset] = (byte) this.methodCount; - - int attributesNumber = 0; - // leave two bytes for the number of attributes and store the current offset - int attributeOffset = this.contentsOffset; - this.contentsOffset += 2; - - // source attribute - if ((this.produceAttributes & ClassFileConstants.ATTR_SOURCE) != 0) { - String fullFileName = - new String(this.referenceBinding.scope.referenceCompilationUnit().getFileName()); - fullFileName = fullFileName.replace('\\', '/'); - int lastIndex = fullFileName.lastIndexOf('/'); - if (lastIndex != -1) { - fullFileName = fullFileName.substring(lastIndex + 1, fullFileName.length()); - } - attributesNumber += generateSourceAttribute(fullFileName); - } - // Deprecated attribute - if (this.referenceBinding.isDeprecated()) { - // check that there is enough space to write all the bytes for the field info corresponding - // to the @fieldBinding - attributesNumber += generateDeprecatedAttribute(); - } - // add signature attribute - char[] genericSignature = this.referenceBinding.genericSignature(); - if (genericSignature != null) { - attributesNumber += generateSignatureAttribute(genericSignature); - } - if (this.targetJDK >= ClassFileConstants.JDK1_5 - && this.referenceBinding.isNestedType() - && !this.referenceBinding.isMemberType()) { - // add enclosing method attribute (1.5 mode only) - attributesNumber += generateEnclosingMethodAttribute(); - } - if (this.targetJDK >= ClassFileConstants.JDK1_4) { - TypeDeclaration typeDeclaration = this.referenceBinding.scope.referenceContext; - if (typeDeclaration != null) { - // AspectJ Extension - use the original array if its set - // original code: - // final Annotation[] annotations = typeDeclaration.annotations; - // new code: - Annotation[] annotations = typeDeclaration.originalAnnotations; - if (annotations == null) annotations = typeDeclaration.annotations; - // End AspectJ Extension - if (annotations != null) { - long targetMask; - if (typeDeclaration.isPackageInfo()) - targetMask = TagBits.AnnotationForPackage; - else if (this.referenceBinding.isAnnotationType()) - targetMask = TagBits.AnnotationForType | TagBits.AnnotationForAnnotationType; - else - targetMask = TagBits.AnnotationForType | TagBits.AnnotationForTypeUse; - attributesNumber += generateRuntimeAnnotations(annotations, targetMask); - } - } - } - - if (this.referenceBinding.isHierarchyInconsistent()) { - ReferenceBinding superclass = this.referenceBinding.superclass; - if (superclass != null) { - this.missingTypes = superclass.collectMissingTypes(this.missingTypes); - } - ReferenceBinding[] superInterfaces = this.referenceBinding.superInterfaces(); - for (int i = 0, max = superInterfaces.length; i < max; i++) { - this.missingTypes = superInterfaces[i].collectMissingTypes(this.missingTypes); - } - attributesNumber += generateHierarchyInconsistentAttribute(); - } - // Functional expression and lambda bootstrap methods - if (this.bootstrapMethods != null && !this.bootstrapMethods.isEmpty()) { - attributesNumber += generateBootstrapMethods(this.bootstrapMethods); - } - // Inner class attribute - int numberOfInnerClasses = this.innerClassesBindings == null ? 0 : this.innerClassesBindings.size(); - if (numberOfInnerClasses != 0) { - ReferenceBinding[] innerClasses = new ReferenceBinding[numberOfInnerClasses]; - this.innerClassesBindings.toArray(innerClasses); - Arrays.sort(innerClasses, new Comparator() { - public int compare(Object o1, Object o2) { - TypeBinding binding1 = (TypeBinding) o1; - TypeBinding binding2 = (TypeBinding) o2; - return CharOperation.compareTo(binding1.constantPoolName(), binding2.constantPoolName()); - } - }); - attributesNumber += generateInnerClassAttribute(numberOfInnerClasses, innerClasses); - } - if (this.missingTypes != null) { - generateMissingTypesAttribute(); - attributesNumber++; - } - - attributesNumber += generateTypeAnnotationAttributeForTypeDeclaration(); - - // AspectJ Extension - // write any "extraAttributes" - if (extraAttributes != null) { - for (int i=0, len=extraAttributes.size(); i < len; i++) { - IAttribute attribute = (IAttribute)extraAttributes.get(i); - short nameIndex = (short)constantPool.literalIndex(attribute.getNameChars()); - writeToContents(attribute.getAllBytes(nameIndex,constantPool)); - attributesNumber++; - } - } - // End AspectJ Extension - - // update the number of attributes - if (attributeOffset + 2 >= this.contents.length) { - resizeContents(2); - } - this.contents[attributeOffset++] = (byte) (attributesNumber >> 8); - this.contents[attributeOffset] = (byte) attributesNumber; - - // resynchronize all offsets of the classfile - this.header = this.constantPool.poolContent; - this.headerOffset = this.constantPool.currentOffset; - int constantPoolCount = this.constantPool.currentIndex; - this.header[this.constantPoolOffset++] = (byte) (constantPoolCount >> 8); - this.header[this.constantPoolOffset] = (byte) constantPoolCount; - } - /** - * INTERNAL USE-ONLY - * This methods generate all the default abstract method infos that correpond to - * the abstract methods inherited from superinterfaces. - */ - public void addDefaultAbstractMethods() { // default abstract methods - MethodBinding[] defaultAbstractMethods = - this.referenceBinding.getDefaultAbstractMethods(); - for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) { - MethodBinding methodBinding = defaultAbstractMethods[i]; - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - int attributeNumber = generateMethodInfoAttributes(methodBinding); - completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber); - } - } - - private int addFieldAttributes(FieldBinding fieldBinding, int fieldAttributeOffset) { - int attributesNumber = 0; - // 4.7.2 only static constant fields get a ConstantAttribute - // Generate the constantValueAttribute - Constant fieldConstant = fieldBinding.constant(); - if (fieldConstant != Constant.NotAConstant){ - attributesNumber += generateConstantValueAttribute(fieldConstant, fieldBinding, fieldAttributeOffset); - } - if (this.targetJDK < ClassFileConstants.JDK1_5 && fieldBinding.isSynthetic()) { - attributesNumber += generateSyntheticAttribute(); - } - if (fieldBinding.isDeprecated()) { - attributesNumber += generateDeprecatedAttribute(); - } - // add signature attribute - char[] genericSignature = fieldBinding.genericSignature(); - if (genericSignature != null) { - attributesNumber += generateSignatureAttribute(genericSignature); - } - if (this.targetJDK >= ClassFileConstants.JDK1_4) { - FieldDeclaration fieldDeclaration = fieldBinding.sourceField(); - if (fieldDeclaration != null) { - Annotation[] annotations = fieldDeclaration.annotations; - if (annotations != null) { - attributesNumber += generateRuntimeAnnotations(annotations, TagBits.AnnotationForField); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) { - List allTypeAnnotationContexts = new ArrayList(); - if (annotations != null && (fieldDeclaration.bits & ASTNode.HasTypeAnnotations) != 0) { - fieldDeclaration.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts); - } - int invisibleTypeAnnotationsCounter = 0; - int visibleTypeAnnotationsCounter = 0; - TypeReference fieldType = fieldDeclaration.type; - if (fieldType != null && ((fieldType.bits & ASTNode.HasTypeAnnotations) != 0)) { - fieldType.getAllAnnotationContexts(AnnotationTargetTypeConstants.FIELD, allTypeAnnotationContexts); - } - int size = allTypeAnnotationContexts.size(); - if (size != 0) { - AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size]; - allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray); - for (int i = 0, max = allTypeAnnotationContextsArray.length; i < max; i++) { - AnnotationContext annotationContext = allTypeAnnotationContextsArray[i]; - if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) { - invisibleTypeAnnotationsCounter++; - allTypeAnnotationContexts.add(annotationContext); - } else { - visibleTypeAnnotationsCounter++; - allTypeAnnotationContexts.add(annotationContext); - } - } - attributesNumber += generateRuntimeTypeAnnotations( - allTypeAnnotationContextsArray, - visibleTypeAnnotationsCounter, - invisibleTypeAnnotationsCounter); - } - } - } - } - if ((fieldBinding.tagBits & TagBits.HasMissingType) != 0) { - this.missingTypes = fieldBinding.type.collectMissingTypes(this.missingTypes); - } - return attributesNumber; - } - - // AspectJ Extension - public List/*<IAttribute>*/ extraAttributes = new ArrayList(1); - // End AspectJ Extension - - /** - * INTERNAL USE-ONLY - * This methods generates the bytes for the given field binding - * @param fieldBinding the given field binding - */ - private void addFieldInfo(FieldBinding fieldBinding) { - // check that there is enough space to write all the bytes for the field info corresponding - // to the @fieldBinding - if (this.contentsOffset + 8 >= this.contents.length) { - resizeContents(8); - } - // Now we can generate all entries into the byte array - // First the accessFlags - int accessFlags = fieldBinding.getAccessFlags(); - if (this.targetJDK < ClassFileConstants.JDK1_5) { - // pre 1.5, synthetic was an attribute, not a modifier - accessFlags &= ~ClassFileConstants.AccSynthetic; - } - this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8); - this.contents[this.contentsOffset++] = (byte) accessFlags; - // Then the nameIndex - int nameIndex = this.constantPool.literalIndex(fieldBinding.name); - this.contents[this.contentsOffset++] = (byte) (nameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) nameIndex; - // Then the descriptorIndex - int descriptorIndex = this.constantPool.literalIndex(fieldBinding.type); - this.contents[this.contentsOffset++] = (byte) (descriptorIndex >> 8); - this.contents[this.contentsOffset++] = (byte) descriptorIndex; - int fieldAttributeOffset = this.contentsOffset; - int attributeNumber = 0; - // leave some space for the number of attributes - this.contentsOffset += 2; - attributeNumber += addFieldAttributes(fieldBinding, fieldAttributeOffset); - if (this.contentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - this.contents[fieldAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[fieldAttributeOffset] = (byte) attributeNumber; - } - - /** - * INTERNAL USE-ONLY - * This methods generate all the fields infos for the receiver. - * This includes: - * - a field info for each defined field of that class - * - a field info for each synthetic field (e.g. this$0) - */ - /** - * INTERNAL USE-ONLY - * This methods generate all the fields infos for the receiver. - * This includes: - * - a field info for each defined field of that class - * - a field info for each synthetic field (e.g. this$0) - */ - public void addFieldInfos() { - SourceTypeBinding currentBinding = this.referenceBinding; - FieldBinding[] syntheticFields = currentBinding.syntheticFields(); - int fieldCount = currentBinding.fieldCount() + (syntheticFields == null ? 0 : syntheticFields.length); - - // write the number of fields - if (fieldCount > 0xFFFF) { - this.referenceBinding.scope.problemReporter().tooManyFields(this.referenceBinding.scope.referenceType()); - } - this.contents[this.contentsOffset++] = (byte) (fieldCount >> 8); - this.contents[this.contentsOffset++] = (byte) fieldCount; - - FieldDeclaration[] fieldDecls = currentBinding.scope.referenceContext.fields; - for (int i = 0, max = fieldDecls == null ? 0 : fieldDecls.length; i < max; i++) { - FieldDeclaration fieldDecl = fieldDecls[i]; - if (fieldDecl.binding != null) { - addFieldInfo(fieldDecl.binding); - } - } - - if (syntheticFields != null) { - for (int i = 0, max = syntheticFields.length; i < max; i++) { - addFieldInfo(syntheticFields[i]); - } - } - } - - private void addMissingAbstractProblemMethod(MethodDeclaration methodDeclaration, MethodBinding methodBinding, CategorizedProblem problem, CompilationResult compilationResult) { - // always clear the strictfp/native/abstract bit for a problem method - generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract)); - int methodAttributeOffset = this.contentsOffset; - int attributeNumber = generateMethodInfoAttributes(methodBinding); - - // Code attribute - attributeNumber++; - - int codeAttributeOffset = this.contentsOffset; - generateCodeAttributeHeader(); - StringBuffer buffer = new StringBuffer(25); - buffer.append("\t" + problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$ - buffer.insert(0, Messages.compilation_unresolvedProblem); - String problemString = buffer.toString(); - - this.codeStream.init(this); - this.codeStream.preserveUnusedLocals = true; - this.codeStream.initializeMaxLocals(methodBinding); - - // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "") - this.codeStream.generateCodeAttributeForProblemMethod(problemString); - - completeCodeAttributeForMissingAbstractProblemMethod( - methodBinding, - codeAttributeOffset, - compilationResult.getLineSeparatorPositions(), - problem.getSourceLineNumber()); - - completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber); - } - - /** - * INTERNAL USE-ONLY - * Generate the byte for a problem clinit method info that correspond to a boggus method. - * - * @param problems org.aspectj.org.eclipse.jdt.internal.compiler.problem.Problem[] - */ - public void addProblemClinit(CategorizedProblem[] problems) { - generateMethodInfoHeaderForClinit(); - // leave two spaces for the number of attributes - this.contentsOffset -= 2; - int attributeOffset = this.contentsOffset; - this.contentsOffset += 2; - int attributeNumber = 0; - - int codeAttributeOffset = this.contentsOffset; - generateCodeAttributeHeader(); - this.codeStream.resetForProblemClinit(this); - String problemString = "" ; //$NON-NLS-1$ - int problemLine = 0; - if (problems != null) { - int max = problems.length; - StringBuffer buffer = new StringBuffer(25); - int count = 0; - for (int i = 0; i < max; i++) { - CategorizedProblem problem = problems[i]; - if ((problem != null) && (problem.isError())) { - buffer.append("\t" +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$ - count++; - if (problemLine == 0) { - problemLine = problem.getSourceLineNumber(); - } - problems[i] = null; - } - } // insert the top line afterwards, once knowing how many problems we have to consider - if (count > 1) { - buffer.insert(0, Messages.compilation_unresolvedProblems); - } else { - buffer.insert(0, Messages.compilation_unresolvedProblem); - } - problemString = buffer.toString(); - } - - // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "") - this.codeStream.generateCodeAttributeForProblemMethod(problemString); - attributeNumber++; // code attribute - completeCodeAttributeForClinit( - codeAttributeOffset, - problemLine); - if (this.contentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - this.contents[attributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[attributeOffset] = (byte) attributeNumber; - } - - /** - * INTERNAL USE-ONLY - * Generate the byte for a problem method info that correspond to a boggus constructor. - * - * @param method org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding - * @param problems org.aspectj.org.eclipse.jdt.internal.compiler.problem.Problem[] - */ - public void addProblemConstructor( - AbstractMethodDeclaration method, - MethodBinding methodBinding, - CategorizedProblem[] problems) { - - if (methodBinding.declaringClass.isInterface()) { - method.abort(ProblemSeverities.AbortType, null); - } - - // always clear the strictfp/native/abstract bit for a problem method - generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract)); - int methodAttributeOffset = this.contentsOffset; - int attributesNumber = generateMethodInfoAttributes(methodBinding); - - // Code attribute - attributesNumber++; - int codeAttributeOffset = this.contentsOffset; - generateCodeAttributeHeader(); - this.codeStream.reset(method, this); - String problemString = "" ; //$NON-NLS-1$ - int problemLine = 0; - if (problems != null) { - int max = problems.length; - StringBuffer buffer = new StringBuffer(25); - int count = 0; - for (int i = 0; i < max; i++) { - CategorizedProblem problem = problems[i]; - if ((problem != null) && (problem.isError())) { - buffer.append("\t" +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$ - count++; - if (problemLine == 0) { - problemLine = problem.getSourceLineNumber(); - } - } - } // insert the top line afterwards, once knowing how many problems we have to consider - if (count > 1) { - buffer.insert(0, Messages.compilation_unresolvedProblems); - } else { - buffer.insert(0, Messages.compilation_unresolvedProblem); - } - problemString = buffer.toString(); - } - - // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "") - this.codeStream.generateCodeAttributeForProblemMethod(problemString); - completeCodeAttributeForProblemMethod( - method, - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions(), - problemLine); - completeMethodInfo(methodBinding, methodAttributeOffset, attributesNumber); - } - /** - * INTERNAL USE-ONLY - * Generate the byte for a problem method info that correspond to a boggus constructor. - * Reset the position inside the contents byte array to the savedOffset. - * - * @param method org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding - * @param problems org.aspectj.org.eclipse.jdt.internal.compiler.problem.Problem[] - * @param savedOffset <CODE>int</CODE> - */ - public void addProblemConstructor( - AbstractMethodDeclaration method, - MethodBinding methodBinding, - CategorizedProblem[] problems, - int savedOffset) { - // we need to move back the contentsOffset to the value at the beginning of the method - this.contentsOffset = savedOffset; - this.methodCount--; // we need to remove the method that causes the problem - addProblemConstructor(method, methodBinding, problems); - } - /** - * INTERNAL USE-ONLY - * Generate the byte for a problem method info that correspond to a boggus method. - * - * @param method org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding - * @param problems org.aspectj.org.eclipse.jdt.internal.compiler.problem.Problem[] - */ - public void addProblemMethod( - AbstractMethodDeclaration method, - MethodBinding methodBinding, - CategorizedProblem[] problems) { - if (methodBinding.isAbstract() && methodBinding.declaringClass.isInterface()) { - method.abort(ProblemSeverities.AbortType, null); - } - // always clear the strictfp/native/abstract bit for a problem method - generateMethodInfoHeader(methodBinding, methodBinding.modifiers & ~(ClassFileConstants.AccStrictfp | ClassFileConstants.AccNative | ClassFileConstants.AccAbstract)); - int methodAttributeOffset = this.contentsOffset; - int attributesNumber = generateMethodInfoAttributes(methodBinding); - - // Code attribute - attributesNumber++; - - int codeAttributeOffset = this.contentsOffset; - generateCodeAttributeHeader(); - this.codeStream.reset(method, this); - String problemString = "" ; //$NON-NLS-1$ - int problemLine = 0; - if (problems != null) { - int max = problems.length; - StringBuffer buffer = new StringBuffer(25); - int count = 0; - for (int i = 0; i < max; i++) { - CategorizedProblem problem = problems[i]; - if ((problem != null) - && (problem.isError()) - && (problem.getSourceStart() >= method.declarationSourceStart) - && (problem.getSourceEnd() <= method.declarationSourceEnd)) { - buffer.append("\t" +problem.getMessage() + "\n" ); //$NON-NLS-1$ //$NON-NLS-2$ - count++; - if (problemLine == 0) { - problemLine = problem.getSourceLineNumber(); - } - problems[i] = null; - } - } // insert the top line afterwards, once knowing how many problems we have to consider - if (count > 1) { - buffer.insert(0, Messages.compilation_unresolvedProblems); - } else { - buffer.insert(0, Messages.compilation_unresolvedProblem); - } - problemString = buffer.toString(); - } - - // return codeStream.generateCodeAttributeForProblemMethod(comp.options.runtimeExceptionNameForCompileError, "") - this.codeStream.generateCodeAttributeForProblemMethod(problemString); - completeCodeAttributeForProblemMethod( - method, - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions(), - problemLine); - completeMethodInfo(methodBinding, methodAttributeOffset, attributesNumber); - } - - /** - * INTERNAL USE-ONLY - * Generate the byte for a problem method info that correspond to a boggus method. - * Reset the position inside the contents byte array to the savedOffset. - * - * @param method org.aspectj.org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.MethodBinding - * @param problems org.aspectj.org.eclipse.jdt.internal.compiler.problem.Problem[] - * @param savedOffset <CODE>int</CODE> - */ - public void addProblemMethod( - AbstractMethodDeclaration method, - MethodBinding methodBinding, - CategorizedProblem[] problems, - int savedOffset) { - // we need to move back the contentsOffset to the value at the beginning of the method - this.contentsOffset = savedOffset; - this.methodCount--; // we need to remove the method that causes the problem - addProblemMethod(method, methodBinding, problems); - } - - /** - * INTERNAL USE-ONLY - * Generate the byte for all the special method infos. - * They are: - * - synthetic access methods - * - default abstract methods - * - lambda methods. - */ - public void addSpecialMethods() { - - // add all methods (default abstract methods and synthetic) - - // default abstract methods - generateMissingAbstractMethods(this.referenceBinding.scope.referenceType().missingAbstractMethods, this.referenceBinding.scope.referenceCompilationUnit().compilationResult); - - MethodBinding[] defaultAbstractMethods = this.referenceBinding.getDefaultAbstractMethods(); - for (int i = 0, max = defaultAbstractMethods.length; i < max; i++) { - MethodBinding methodBinding = defaultAbstractMethods[i]; - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - int attributeNumber = generateMethodInfoAttributes(methodBinding); - completeMethodInfo(methodBinding, methodAttributeOffset, attributeNumber); - } - - // add synthetic methods infos - int emittedSyntheticsCount = 0; - boolean continueScanningSynthetics = true; - while (continueScanningSynthetics) { - continueScanningSynthetics = false; - SyntheticMethodBinding[] syntheticMethods = this.referenceBinding.syntheticMethods(); - int currentSyntheticsCount = syntheticMethods == null ? 0: syntheticMethods.length; - if (emittedSyntheticsCount != currentSyntheticsCount) { - for (int i = emittedSyntheticsCount, max = currentSyntheticsCount; i < max; i++) { - SyntheticMethodBinding syntheticMethod = syntheticMethods[i]; - switch (syntheticMethod.purpose) { - case SyntheticMethodBinding.FieldReadAccess : - case SyntheticMethodBinding.SuperFieldReadAccess : - // generate a method info to emulate an reading access to - // a non-accessible field - addSyntheticFieldReadAccessMethod(syntheticMethod); - break; - case SyntheticMethodBinding.FieldWriteAccess : - case SyntheticMethodBinding.SuperFieldWriteAccess : - // generate a method info to emulate an writing access to - // a non-accessible field - addSyntheticFieldWriteAccessMethod(syntheticMethod); - break; - case SyntheticMethodBinding.MethodAccess : - case SyntheticMethodBinding.SuperMethodAccess : - case SyntheticMethodBinding.BridgeMethod : - // generate a method info to emulate an access to a non-accessible method / super-method or bridge method - addSyntheticMethodAccessMethod(syntheticMethod); - break; - case SyntheticMethodBinding.ConstructorAccess : - // generate a method info to emulate an access to a non-accessible constructor - addSyntheticConstructorAccessMethod(syntheticMethod); - break; - case SyntheticMethodBinding.EnumValues : - // generate a method info to define <enum>#values() - addSyntheticEnumValuesMethod(syntheticMethod); - break; - case SyntheticMethodBinding.EnumValueOf : - // generate a method info to define <enum>#valueOf(String) - addSyntheticEnumValueOfMethod(syntheticMethod); - break; - case SyntheticMethodBinding.SwitchTable : - // generate a method info to define the switch table synthetic method - addSyntheticSwitchTable(syntheticMethod); - break; - case SyntheticMethodBinding.TooManyEnumsConstants : - addSyntheticEnumInitializationMethod(syntheticMethod); - break; - case SyntheticMethodBinding.LambdaMethod: - syntheticMethod.lambda.generateCode(this.referenceBinding.scope, this); - continueScanningSynthetics = true; // lambda code generation could schedule additional nested lambdas for code generation. - break; - case SyntheticMethodBinding.ArrayConstructor: - addSyntheticArrayConstructor(syntheticMethod); - break; - case SyntheticMethodBinding.ArrayClone: - addSyntheticArrayClone(syntheticMethod); - break; - case SyntheticMethodBinding.FactoryMethod: - addSyntheticFactoryMethod(syntheticMethod); - break; - case SyntheticMethodBinding.DeserializeLambda: - // TODO [andy] do we need to do this after the loop to ensure it is done last? - addSyntheticDeserializeLambda(syntheticMethod,this.referenceBinding.syntheticMethods()); - break; - } - } - emittedSyntheticsCount = currentSyntheticsCount; - } - } - } - - public void addSyntheticArrayConstructor(SyntheticMethodBinding methodBinding) { - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - // this will add exception attribute, synthetic attribute, deprecated attribute,... - int attributeNumber = generateMethodInfoAttributes(methodBinding); - // Code attribute - int codeAttributeOffset = this.contentsOffset; - attributeNumber++; // add code attribute - generateCodeAttributeHeader(); - this.codeStream.init(this); - this.codeStream.generateSyntheticBodyForArrayConstructor(methodBinding); - completeCodeAttributeForSyntheticMethod( - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions()); - // update the number of attributes - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; - } - public void addSyntheticArrayClone(SyntheticMethodBinding methodBinding) { - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - // this will add exception attribute, synthetic attribute, deprecated attribute,... - int attributeNumber = generateMethodInfoAttributes(methodBinding); - // Code attribute - int codeAttributeOffset = this.contentsOffset; - attributeNumber++; // add code attribute - generateCodeAttributeHeader(); - this.codeStream.init(this); - this.codeStream.generateSyntheticBodyForArrayClone(methodBinding); - completeCodeAttributeForSyntheticMethod( - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions()); - // update the number of attributes - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; - } - public void addSyntheticFactoryMethod(SyntheticMethodBinding methodBinding) { - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - // this will add exception attribute, synthetic attribute, deprecated attribute,... - int attributeNumber = generateMethodInfoAttributes(methodBinding); - // Code attribute - int codeAttributeOffset = this.contentsOffset; - attributeNumber++; // add code attribute - generateCodeAttributeHeader(); - this.codeStream.init(this); - this.codeStream.generateSyntheticBodyForFactoryMethod(methodBinding); - completeCodeAttributeForSyntheticMethod( - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions()); - // update the number of attributes - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; - } - /** - * INTERNAL USE-ONLY - * Generate the bytes for a synthetic method that provides an access to a private constructor. - * - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding - */ - public void addSyntheticConstructorAccessMethod(SyntheticMethodBinding methodBinding) { - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - // this will add exception attribute, synthetic attribute, deprecated attribute,... - int attributeNumber = generateMethodInfoAttributes(methodBinding); - // Code attribute - int codeAttributeOffset = this.contentsOffset; - attributeNumber++; // add code attribute - generateCodeAttributeHeader(); - this.codeStream.init(this); - this.codeStream.generateSyntheticBodyForConstructorAccess(methodBinding); - completeCodeAttributeForSyntheticMethod( - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions()); - // update the number of attributes - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; - } - - /** - * INTERNAL USE-ONLY - * Generate the bytes for a synthetic method that implements Enum#valueOf(String) for a given enum type - * - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding - */ - public void addSyntheticEnumValueOfMethod(SyntheticMethodBinding methodBinding) { - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - // this will add exception attribute, synthetic attribute, deprecated attribute,... - int attributeNumber = generateMethodInfoAttributes(methodBinding); - // Code attribute - int codeAttributeOffset = this.contentsOffset; - attributeNumber++; // add code attribute - generateCodeAttributeHeader(); - this.codeStream.init(this); - this.codeStream.generateSyntheticBodyForEnumValueOf(methodBinding); - completeCodeAttributeForSyntheticMethod( - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions()); - // update the number of attributes - if ((this.produceAttributes & ClassFileConstants.ATTR_METHOD_PARAMETERS) != 0) { - attributeNumber += generateMethodParameters(methodBinding); - } - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; - } - - /** - * INTERNAL USE-ONLY - * Generate the bytes for a synthetic method that implements Enum#values() for a given enum type - * - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding - */ - public void addSyntheticEnumValuesMethod(SyntheticMethodBinding methodBinding) { - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - // this will add exception attribute, synthetic attribute, deprecated attribute,... - int attributeNumber = generateMethodInfoAttributes(methodBinding); - // Code attribute - int codeAttributeOffset = this.contentsOffset; - attributeNumber++; // add code attribute - generateCodeAttributeHeader(); - this.codeStream.init(this); - this.codeStream.generateSyntheticBodyForEnumValues(methodBinding); - completeCodeAttributeForSyntheticMethod( - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions()); - // update the number of attributes - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; - } - - public void addSyntheticEnumInitializationMethod(SyntheticMethodBinding methodBinding) { - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - // this will add exception attribute, synthetic attribute, deprecated attribute,... - int attributeNumber = generateMethodInfoAttributes(methodBinding); - // Code attribute - int codeAttributeOffset = this.contentsOffset; - attributeNumber++; // add code attribute - generateCodeAttributeHeader(); - this.codeStream.init(this); - this.codeStream.generateSyntheticBodyForEnumInitializationMethod(methodBinding); - completeCodeAttributeForSyntheticMethod( - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions()); - // update the number of attributes - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; - } - /** - * INTERNAL USE-ONLY - * Generate the byte for a problem method info that correspond to a synthetic method that - * generate an read access to a private field. - * - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding - */ - public void addSyntheticFieldReadAccessMethod(SyntheticMethodBinding methodBinding) { - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - // this will add exception attribute, synthetic attribute, deprecated attribute,... - int attributeNumber = generateMethodInfoAttributes(methodBinding); - // Code attribute - int codeAttributeOffset = this.contentsOffset; - attributeNumber++; // add code attribute - generateCodeAttributeHeader(); - this.codeStream.init(this); - this.codeStream.generateSyntheticBodyForFieldReadAccess(methodBinding); - completeCodeAttributeForSyntheticMethod( - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions()); - // update the number of attributes - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; - } - - /** - * INTERNAL USE-ONLY - * Generate the byte for a problem method info that correspond to a synthetic method that - * generate an write access to a private field. - * - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding - */ - public void addSyntheticFieldWriteAccessMethod(SyntheticMethodBinding methodBinding) { - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - // this will add exception attribute, synthetic attribute, deprecated attribute,... - int attributeNumber = generateMethodInfoAttributes(methodBinding); - // Code attribute - int codeAttributeOffset = this.contentsOffset; - attributeNumber++; // add code attribute - generateCodeAttributeHeader(); - this.codeStream.init(this); - this.codeStream.generateSyntheticBodyForFieldWriteAccess(methodBinding); - completeCodeAttributeForSyntheticMethod( - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions()); - // update the number of attributes - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; - } - - /** - * INTERNAL USE-ONLY - * Generate the bytes for a synthetic method that provides access to a private method. - * - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.nameloopkup.SyntheticAccessMethodBinding - */ - public void addSyntheticMethodAccessMethod(SyntheticMethodBinding methodBinding) { - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - // this will add exception attribute, synthetic attribute, deprecated attribute,... - int attributeNumber = generateMethodInfoAttributes(methodBinding); - // Code attribute - int codeAttributeOffset = this.contentsOffset; - attributeNumber++; // add code attribute - generateCodeAttributeHeader(); - this.codeStream.init(this); - this.codeStream.generateSyntheticBodyForMethodAccess(methodBinding); - completeCodeAttributeForSyntheticMethod( - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions()); - // update the number of attributes - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; - } - - public void addSyntheticSwitchTable(SyntheticMethodBinding methodBinding) { - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - // this will add exception attribute, synthetic attribute, deprecated attribute,... - int attributeNumber = generateMethodInfoAttributes(methodBinding); - // Code attribute - int codeAttributeOffset = this.contentsOffset; - attributeNumber++; // add code attribute - generateCodeAttributeHeader(); - this.codeStream.init(this); - this.codeStream.generateSyntheticBodyForSwitchTable(methodBinding); - completeCodeAttributeForSyntheticMethod( - true, - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions()); - // update the number of attributes - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; - } - - /** - * INTERNAL USE-ONLY - * That method completes the creation of the code attribute by setting - * - the attribute_length - * - max_stack - * - max_locals - * - code_length - * - exception table - * - and debug attributes if necessary. - * - * @param codeAttributeOffset <CODE>int</CODE> - */ - public void completeCodeAttribute(int codeAttributeOffset) { - // reinitialize the localContents with the byte modified by the code stream - this.contents = this.codeStream.bCodeStream; - int localContentsOffset = this.codeStream.classFileOffset; - // codeAttributeOffset is the position inside localContents byte array before we started to write - // any information about the codeAttribute - // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset - // to get the right position, 6 for the max_stack etc... - int code_length = this.codeStream.position; - if (code_length > 65535) { - if (this.codeStream.methodDeclaration != null) { - this.codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit(this.codeStream.methodDeclaration); - } else { - this.codeStream.lambdaExpression.scope.problemReporter().bytecodeExceeds64KLimit(this.codeStream.lambdaExpression); - } - } - if (localContentsOffset + 20 >= this.contents.length) { - resizeContents(20); - } - int max_stack = this.codeStream.stackMax; - this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8); - this.contents[codeAttributeOffset + 7] = (byte) max_stack; - int max_locals = this.codeStream.maxLocals; - this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8); - this.contents[codeAttributeOffset + 9] = (byte) max_locals; - this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24); - this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16); - this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8); - this.contents[codeAttributeOffset + 13] = (byte) code_length; - - boolean addStackMaps = (this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0; - // write the exception table - ExceptionLabel[] exceptionLabels = this.codeStream.exceptionLabels; - int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous) - for (int i = 0, length = this.codeStream.exceptionLabelsCounter; i < length; i++) { - exceptionHandlersCount += this.codeStream.exceptionLabels[i].getCount() / 2; - } - int exSize = exceptionHandlersCount * 8 + 2; - if (exSize + localContentsOffset >= this.contents.length) { - resizeContents(exSize); - } - // there is no exception table, so we need to offset by 2 the current offset and move - // on the attribute generation - this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8); - this.contents[localContentsOffset++] = (byte) exceptionHandlersCount; - for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) { - ExceptionLabel exceptionLabel = exceptionLabels[i]; - if (exceptionLabel != null) { - int iRange = 0, maxRange = exceptionLabel.getCount(); - if ((maxRange & 1) != 0) { - if (this.codeStream.methodDeclaration != null) { - this.codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError( - Messages.bind(Messages.abort_invalidExceptionAttribute, new String(this.codeStream.methodDeclaration.selector)), - this.codeStream.methodDeclaration); - } else { - this.codeStream.lambdaExpression.scope.problemReporter().abortDueToInternalError( - Messages.bind(Messages.abort_invalidExceptionAttribute, new String(this.codeStream.lambdaExpression.binding.selector)), - this.codeStream.lambdaExpression); - } - } - while (iRange < maxRange) { - int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions - this.contents[localContentsOffset++] = (byte) (start >> 8); - this.contents[localContentsOffset++] = (byte) start; - int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions - this.contents[localContentsOffset++] = (byte) (end >> 8); - this.contents[localContentsOffset++] = (byte) end; - int handlerPC = exceptionLabel.position; - if (addStackMaps) { - StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream; - stackMapFrameCodeStream.addFramePosition(handlerPC); -// stackMapFrameCodeStream.addExceptionMarker(handlerPC, exceptionLabel.exceptionType); - } - this.contents[localContentsOffset++] = (byte) (handlerPC >> 8); - this.contents[localContentsOffset++] = (byte) handlerPC; - if (exceptionLabel.exceptionType == null) { - // any exception handler - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - } else { - int nameIndex; - if (exceptionLabel.exceptionType == TypeBinding.NULL) { - /* represents ClassNotFoundException, see class literal access*/ - nameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName); - } else { - nameIndex = this.constantPool.literalIndexForType(exceptionLabel.exceptionType); - } - this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); - this.contents[localContentsOffset++] = (byte) nameIndex; - } - } - } - } - // debug attributes - int codeAttributeAttributeOffset = localContentsOffset; - int attributesNumber = 0; - // leave two bytes for the attribute_length - localContentsOffset += 2; - if (localContentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - - this.contentsOffset = localContentsOffset; - - // first we handle the linenumber attribute - if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { - attributesNumber += generateLineNumberAttribute(); - } - // then we do the local variable attribute - if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) { - final boolean methodDeclarationIsStatic = this.codeStream.methodDeclaration != null ? this.codeStream.methodDeclaration.isStatic() : this.codeStream.lambdaExpression.binding.isStatic(); - attributesNumber += generateLocalVariableTableAttribute(code_length, methodDeclarationIsStatic, false); - } - - if (addStackMaps) { - attributesNumber += generateStackMapTableAttribute( - this.codeStream.methodDeclaration != null ? this.codeStream.methodDeclaration.binding : this.codeStream.lambdaExpression.binding, - code_length, - codeAttributeOffset, - max_locals, - false); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) { - attributesNumber += generateStackMapAttribute( - this.codeStream.methodDeclaration != null ? this.codeStream.methodDeclaration.binding : this.codeStream.lambdaExpression.binding, - code_length, - codeAttributeOffset, - max_locals, - false); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) { - attributesNumber += generateTypeAnnotationsOnCodeAttribute(); - } - - this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8); - this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; - - // update the attribute length - int codeAttributeLength = this.contentsOffset - (codeAttributeOffset + 6); - this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24); - this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16); - this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8); - this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength; - } - - public int generateTypeAnnotationsOnCodeAttribute() { - int attributesNumber = 0; - - List allTypeAnnotationContexts = ((TypeAnnotationCodeStream) this.codeStream).allTypeAnnotationContexts; - int invisibleTypeAnnotationsCounter = 0; - int visibleTypeAnnotationsCounter = 0; - - for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) { - LocalVariableBinding localVariable = this.codeStream.locals[i]; - if (localVariable.isCatchParameter()) continue; - LocalDeclaration declaration = localVariable.declaration; - if (declaration == null - || (declaration.isArgument() && ((declaration.bits & ASTNode.IsUnionType) == 0)) - || (localVariable.initializationCount == 0) - || ((declaration.bits & ASTNode.HasTypeAnnotations) == 0)) { - continue; - } - int targetType = ((localVariable.tagBits & TagBits.IsResource) == 0) ? AnnotationTargetTypeConstants.LOCAL_VARIABLE : AnnotationTargetTypeConstants.RESOURCE_VARIABLE; - declaration.getAllAnnotationContexts(targetType, localVariable, allTypeAnnotationContexts); - } - - ExceptionLabel[] exceptionLabels = this.codeStream.exceptionLabels; - for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) { - ExceptionLabel exceptionLabel = exceptionLabels[i]; - if (exceptionLabel.exceptionTypeReference != null && (exceptionLabel.exceptionTypeReference.bits & ASTNode.HasTypeAnnotations) != 0) { - exceptionLabel.exceptionTypeReference.getAllAnnotationContexts(AnnotationTargetTypeConstants.EXCEPTION_PARAMETER, i, allTypeAnnotationContexts, exceptionLabel.se7Annotations); - } - } - - int size = allTypeAnnotationContexts.size(); - if (size != 0) { - AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size]; - allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray); - for (int j = 0, max2 = allTypeAnnotationContextsArray.length; j < max2; j++) { - AnnotationContext annotationContext = allTypeAnnotationContextsArray[j]; - if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) { - invisibleTypeAnnotationsCounter++; - } else { - visibleTypeAnnotationsCounter++; - } - } - attributesNumber += generateRuntimeTypeAnnotations( - allTypeAnnotationContextsArray, - visibleTypeAnnotationsCounter, - invisibleTypeAnnotationsCounter); - } - return attributesNumber; - } - - /** - * INTERNAL USE-ONLY - * That method completes the creation of the code attribute by setting - * - the attribute_length - * - max_stack - * - max_locals - * - code_length - * - exception table - * - and debug attributes if necessary. - * - * @param codeAttributeOffset <CODE>int</CODE> - */ - public void completeCodeAttributeForClinit(int codeAttributeOffset) { - // reinitialize the contents with the byte modified by the code stream - this.contents = this.codeStream.bCodeStream; - int localContentsOffset = this.codeStream.classFileOffset; - // codeAttributeOffset is the position inside contents byte array before we started to write - // any information about the codeAttribute - // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset - // to get the right position, 6 for the max_stack etc... - int code_length = this.codeStream.position; - if (code_length > 65535) { - this.codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit( - this.codeStream.methodDeclaration.scope.referenceType()); - } - if (localContentsOffset + 20 >= this.contents.length) { - resizeContents(20); - } - int max_stack = this.codeStream.stackMax; - this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8); - this.contents[codeAttributeOffset + 7] = (byte) max_stack; - int max_locals = this.codeStream.maxLocals; - this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8); - this.contents[codeAttributeOffset + 9] = (byte) max_locals; - this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24); - this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16); - this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8); - this.contents[codeAttributeOffset + 13] = (byte) code_length; - - boolean addStackMaps = (this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0; - // write the exception table - ExceptionLabel[] exceptionLabels = this.codeStream.exceptionLabels; - int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous) - for (int i = 0, length = this.codeStream.exceptionLabelsCounter; i < length; i++) { - exceptionHandlersCount += this.codeStream.exceptionLabels[i].getCount() / 2; - } - int exSize = exceptionHandlersCount * 8 + 2; - if (exSize + localContentsOffset >= this.contents.length) { - resizeContents(exSize); - } - // there is no exception table, so we need to offset by 2 the current offset and move - // on the attribute generation - this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8); - this.contents[localContentsOffset++] = (byte) exceptionHandlersCount; - for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) { - ExceptionLabel exceptionLabel = exceptionLabels[i]; - if (exceptionLabel != null) { - int iRange = 0, maxRange = exceptionLabel.getCount(); - if ((maxRange & 1) != 0) { - this.codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError( - Messages.bind(Messages.abort_invalidExceptionAttribute, new String(this.codeStream.methodDeclaration.selector)), - this.codeStream.methodDeclaration); - } - while (iRange < maxRange) { - int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions - this.contents[localContentsOffset++] = (byte) (start >> 8); - this.contents[localContentsOffset++] = (byte) start; - int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions - this.contents[localContentsOffset++] = (byte) (end >> 8); - this.contents[localContentsOffset++] = (byte) end; - int handlerPC = exceptionLabel.position; - this.contents[localContentsOffset++] = (byte) (handlerPC >> 8); - this.contents[localContentsOffset++] = (byte) handlerPC; - if (addStackMaps) { - StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream; - stackMapFrameCodeStream.addFramePosition(handlerPC); -// stackMapFrameCodeStream.addExceptionMarker(handlerPC, exceptionLabel.exceptionType); - } - if (exceptionLabel.exceptionType == null) { - // any exception handler - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - } else { - int nameIndex; - if (exceptionLabel.exceptionType == TypeBinding.NULL) { - /* represents denote ClassNotFoundException, see class literal access*/ - nameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName); - } else { - nameIndex = this.constantPool.literalIndexForType(exceptionLabel.exceptionType); - } - this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); - this.contents[localContentsOffset++] = (byte) nameIndex; - } - } - } - } - // debug attributes - int codeAttributeAttributeOffset = localContentsOffset; - int attributesNumber = 0; - // leave two bytes for the attribute_length - localContentsOffset += 2; - if (localContentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - - this.contentsOffset = localContentsOffset; - - // first we handle the linenumber attribute - if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { - attributesNumber += generateLineNumberAttribute(); - } - // then we do the local variable attribute - if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) { - attributesNumber += generateLocalVariableTableAttribute(code_length, true, false); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) { - attributesNumber += generateStackMapTableAttribute( - null, - code_length, - codeAttributeOffset, - max_locals, - true); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) { - attributesNumber += generateStackMapAttribute( - null, - code_length, - codeAttributeOffset, - max_locals, - true); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) { - attributesNumber += generateTypeAnnotationsOnCodeAttribute(); - } - - // update the number of attributes - // ensure first that there is enough space available inside the contents array - if (codeAttributeAttributeOffset + 2 >= this.contents.length) { - resizeContents(2); - } - this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8); - this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; - // update the attribute length - int codeAttributeLength = this.contentsOffset - (codeAttributeOffset + 6); - this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24); - this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16); - this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8); - this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength; - } - - /** - * INTERNAL USE-ONLY - * That method completes the creation of the code attribute by setting - * - the attribute_length - * - max_stack - * - max_locals - * - code_length - * - exception table - * - and debug attributes if necessary. - */ - public void completeCodeAttributeForClinit( - int codeAttributeOffset, - int problemLine) { - // reinitialize the contents with the byte modified by the code stream - this.contents = this.codeStream.bCodeStream; - int localContentsOffset = this.codeStream.classFileOffset; - // codeAttributeOffset is the position inside contents byte array before we started to write - // any information about the codeAttribute - // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset - // to get the right position, 6 for the max_stack etc... - int code_length = this.codeStream.position; - if (code_length > 65535) { - this.codeStream.methodDeclaration.scope.problemReporter().bytecodeExceeds64KLimit( - this.codeStream.methodDeclaration.scope.referenceType()); - } - if (localContentsOffset + 20 >= this.contents.length) { - resizeContents(20); - } - int max_stack = this.codeStream.stackMax; - this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8); - this.contents[codeAttributeOffset + 7] = (byte) max_stack; - int max_locals = this.codeStream.maxLocals; - this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8); - this.contents[codeAttributeOffset + 9] = (byte) max_locals; - this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24); - this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16); - this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8); - this.contents[codeAttributeOffset + 13] = (byte) code_length; - - // write the exception table - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - - // debug attributes - int codeAttributeAttributeOffset = localContentsOffset; - int attributesNumber = 0; // leave two bytes for the attribute_length - localContentsOffset += 2; // first we handle the linenumber attribute - if (localContentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - - this.contentsOffset = localContentsOffset; - // first we handle the linenumber attribute - if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { - attributesNumber += generateLineNumberAttribute(problemLine); - } - localContentsOffset = this.contentsOffset; - // then we do the local variable attribute - if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) { - int localVariableNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName); - if (localContentsOffset + 8 >= this.contents.length) { - resizeContents(8); - } - this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) localVariableNameIndex; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 2; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - attributesNumber++; - } - - this.contentsOffset = localContentsOffset; - - if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) { - attributesNumber += generateStackMapTableAttribute( - null, - code_length, - codeAttributeOffset, - max_locals, - true); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) { - attributesNumber += generateStackMapAttribute( - null, - code_length, - codeAttributeOffset, - max_locals, - true); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) { - attributesNumber += generateTypeAnnotationsOnCodeAttribute(); - } - - // update the number of attributes - // ensure first that there is enough space available inside the contents array - if (codeAttributeAttributeOffset + 2 >= this.contents.length) { - resizeContents(2); - } - this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8); - this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; - // update the attribute length - int codeAttributeLength = this.contentsOffset - (codeAttributeOffset + 6); - this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24); - this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16); - this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8); - this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength; - } - - - /** - * - */ - public void completeCodeAttributeForMissingAbstractProblemMethod( - MethodBinding binding, - int codeAttributeOffset, - int[] startLineIndexes, - int problemLine) { - // reinitialize the localContents with the byte modified by the code stream - this.contents = this.codeStream.bCodeStream; - int localContentsOffset = this.codeStream.classFileOffset; - // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc... - int max_stack = this.codeStream.stackMax; - this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8); - this.contents[codeAttributeOffset + 7] = (byte) max_stack; - int max_locals = this.codeStream.maxLocals; - this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8); - this.contents[codeAttributeOffset + 9] = (byte) max_locals; - int code_length = this.codeStream.position; - this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24); - this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16); - this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8); - this.contents[codeAttributeOffset + 13] = (byte) code_length; - // write the exception table - if (localContentsOffset + 50 >= this.contents.length) { - resizeContents(50); - } - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - // debug attributes - int codeAttributeAttributeOffset = localContentsOffset; - int attributesNumber = 0; // leave two bytes for the attribute_length - localContentsOffset += 2; // first we handle the linenumber attribute - if (localContentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - - this.contentsOffset = localContentsOffset; - if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { - if (problemLine == 0) { - problemLine = Util.getLineNumber(binding.sourceStart(), startLineIndexes, 0, startLineIndexes.length-1); - } - attributesNumber += generateLineNumberAttribute(problemLine); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) { - attributesNumber += generateStackMapTableAttribute( - binding, - code_length, - codeAttributeOffset, - max_locals, - false); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) { - attributesNumber += generateStackMapAttribute( - binding, - code_length, - codeAttributeOffset, - max_locals, - false); - } - - // then we do the local variable attribute - // update the number of attributes// ensure first that there is enough space available inside the localContents array - if (codeAttributeAttributeOffset + 2 >= this.contents.length) { - resizeContents(2); - } - this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8); - this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; - // update the attribute length - int codeAttributeLength = this.contentsOffset - (codeAttributeOffset + 6); - this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24); - this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16); - this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8); - this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength; - } - - /** - * INTERNAL USE-ONLY - * That method completes the creation of the code attribute by setting - * - the attribute_length - * - max_stack - * - max_locals - * - code_length - * - exception table - * - and debug attributes if necessary. - * - * @param codeAttributeOffset <CODE>int</CODE> - */ - public void completeCodeAttributeForProblemMethod( - AbstractMethodDeclaration method, - MethodBinding binding, - int codeAttributeOffset, - int[] startLineIndexes, - int problemLine) { - // reinitialize the localContents with the byte modified by the code stream - this.contents = this.codeStream.bCodeStream; - int localContentsOffset = this.codeStream.classFileOffset; - // codeAttributeOffset is the position inside localContents byte array before we started to write// any information about the codeAttribute// That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset// to get the right position, 6 for the max_stack etc... - int max_stack = this.codeStream.stackMax; - this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8); - this.contents[codeAttributeOffset + 7] = (byte) max_stack; - int max_locals = this.codeStream.maxLocals; - this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8); - this.contents[codeAttributeOffset + 9] = (byte) max_locals; - int code_length = this.codeStream.position; - this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24); - this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16); - this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8); - this.contents[codeAttributeOffset + 13] = (byte) code_length; - // write the exception table - if (localContentsOffset + 50 >= this.contents.length) { - resizeContents(50); - } - - // write the exception table - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - // debug attributes - int codeAttributeAttributeOffset = localContentsOffset; - int attributesNumber = 0; // leave two bytes for the attribute_length - localContentsOffset += 2; // first we handle the linenumber attribute - if (localContentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - - this.contentsOffset = localContentsOffset; - if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { - if (problemLine == 0) { - problemLine = Util.getLineNumber(binding.sourceStart(), startLineIndexes, 0, startLineIndexes.length-1); - } - attributesNumber += generateLineNumberAttribute(problemLine); - } - - // then we do the local variable attribute - if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) { - final boolean methodDeclarationIsStatic = this.codeStream.methodDeclaration.isStatic(); - attributesNumber += generateLocalVariableTableAttribute(code_length, methodDeclarationIsStatic, false); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0) { - attributesNumber += generateStackMapTableAttribute( - binding, - code_length, - codeAttributeOffset, - max_locals, - false); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) { - attributesNumber += generateStackMapAttribute( - binding, - code_length, - codeAttributeOffset, - max_locals, - false); - } - - // update the number of attributes// ensure first that there is enough space available inside the localContents array - if (codeAttributeAttributeOffset + 2 >= this.contents.length) { - resizeContents(2); - } - this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8); - this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; - // update the attribute length - int codeAttributeLength = this.contentsOffset - (codeAttributeOffset + 6); - this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24); - this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16); - this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8); - this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength; - } - - /** - * INTERNAL USE-ONLY - * That method completes the creation of the code attribute by setting - * - the attribute_length - * - max_stack - * - max_locals - * - code_length - * - exception table - * - and debug attributes if necessary. - * - * @param binding org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding - * @param codeAttributeOffset <CODE>int</CODE> - */ - public void completeCodeAttributeForSyntheticMethod( - boolean hasExceptionHandlers, - SyntheticMethodBinding binding, - int codeAttributeOffset, - int[] startLineIndexes) { - // reinitialize the contents with the byte modified by the code stream - this.contents = this.codeStream.bCodeStream; - int localContentsOffset = this.codeStream.classFileOffset; - // codeAttributeOffset is the position inside contents byte array before we started to write - // any information about the codeAttribute - // That means that to write the attribute_length you need to offset by 2 the value of codeAttributeOffset - // to get the right position, 6 for the max_stack etc... - int max_stack = this.codeStream.stackMax; - this.contents[codeAttributeOffset + 6] = (byte) (max_stack >> 8); - this.contents[codeAttributeOffset + 7] = (byte) max_stack; - int max_locals = this.codeStream.maxLocals; - this.contents[codeAttributeOffset + 8] = (byte) (max_locals >> 8); - this.contents[codeAttributeOffset + 9] = (byte) max_locals; - int code_length = this.codeStream.position; - this.contents[codeAttributeOffset + 10] = (byte) (code_length >> 24); - this.contents[codeAttributeOffset + 11] = (byte) (code_length >> 16); - this.contents[codeAttributeOffset + 12] = (byte) (code_length >> 8); - this.contents[codeAttributeOffset + 13] = (byte) code_length; - if ((localContentsOffset + 40) >= this.contents.length) { - resizeContents(40); - } - - boolean addStackMaps = (this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP_TABLE) != 0; - if (hasExceptionHandlers) { - // write the exception table - ExceptionLabel[] exceptionLabels = this.codeStream.exceptionLabels; - int exceptionHandlersCount = 0; // each label holds one handler per range (start/end contiguous) - for (int i = 0, length = this.codeStream.exceptionLabelsCounter; i < length; i++) { - exceptionHandlersCount += this.codeStream.exceptionLabels[i].getCount() / 2; - } - int exSize = exceptionHandlersCount * 8 + 2; - if (exSize + localContentsOffset >= this.contents.length) { - resizeContents(exSize); - } - // there is no exception table, so we need to offset by 2 the current offset and move - // on the attribute generation - this.contents[localContentsOffset++] = (byte) (exceptionHandlersCount >> 8); - this.contents[localContentsOffset++] = (byte) exceptionHandlersCount; - for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) { - ExceptionLabel exceptionLabel = exceptionLabels[i]; - if (exceptionLabel != null) { - int iRange = 0, maxRange = exceptionLabel.getCount(); - if ((maxRange & 1) != 0) { - this.referenceBinding.scope.problemReporter().abortDueToInternalError( - Messages.bind(Messages.abort_invalidExceptionAttribute, new String(binding.selector), - this.referenceBinding.scope.problemReporter().referenceContext)); - } - while (iRange < maxRange) { - int start = exceptionLabel.ranges[iRange++]; // even ranges are start positions - this.contents[localContentsOffset++] = (byte) (start >> 8); - this.contents[localContentsOffset++] = (byte) start; - int end = exceptionLabel.ranges[iRange++]; // odd ranges are end positions - this.contents[localContentsOffset++] = (byte) (end >> 8); - this.contents[localContentsOffset++] = (byte) end; - int handlerPC = exceptionLabel.position; - if (addStackMaps) { - StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream; - stackMapFrameCodeStream.addFramePosition(handlerPC); - } - this.contents[localContentsOffset++] = (byte) (handlerPC >> 8); - this.contents[localContentsOffset++] = (byte) handlerPC; - if (exceptionLabel.exceptionType == null) { - // any exception handler - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - } else { - int nameIndex; - switch(exceptionLabel.exceptionType.id) { - case T_null : - /* represents ClassNotFoundException, see class literal access*/ - nameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangClassNotFoundExceptionConstantPoolName); - break; - case T_long : - /* represents NoSuchFieldError, see switch table generation*/ - nameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangNoSuchFieldErrorConstantPoolName); - break; - default: - nameIndex = this.constantPool.literalIndexForType(exceptionLabel.exceptionType); - } - this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); - this.contents[localContentsOffset++] = (byte) nameIndex; - } - } - } - } - } else { - // there is no exception table, so we need to offset by 2 the current offset and move - // on the attribute generation - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - } - // debug attributes - int codeAttributeAttributeOffset = localContentsOffset; - int attributesNumber = 0; - // leave two bytes for the attribute_length - localContentsOffset += 2; - if (localContentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - - this.contentsOffset = localContentsOffset; - // first we handle the linenumber attribute - if ((this.produceAttributes & ClassFileConstants.ATTR_LINES) != 0) { - int lineNumber = Util.getLineNumber(binding.sourceStart, startLineIndexes, 0, startLineIndexes.length-1); - attributesNumber += generateLineNumberAttribute(lineNumber); - } - // then we do the local variable attribute - if ((this.produceAttributes & ClassFileConstants.ATTR_VARS) != 0) { - final boolean methodDeclarationIsStatic = binding.isStatic(); - attributesNumber += generateLocalVariableTableAttribute(code_length, methodDeclarationIsStatic, true); - } - if (addStackMaps) { - attributesNumber += generateStackMapTableAttribute(binding, code_length, codeAttributeOffset, max_locals, false); - } - - if ((this.produceAttributes & ClassFileConstants.ATTR_STACK_MAP) != 0) { - attributesNumber += generateStackMapAttribute( - binding, - code_length, - codeAttributeOffset, - max_locals, - false); - } - - // update the number of attributes - // ensure first that there is enough space available inside the contents array - if (codeAttributeAttributeOffset + 2 >= this.contents.length) { - resizeContents(2); - } - this.contents[codeAttributeAttributeOffset++] = (byte) (attributesNumber >> 8); - this.contents[codeAttributeAttributeOffset] = (byte) attributesNumber; - - // update the attribute length - int codeAttributeLength = this.contentsOffset - (codeAttributeOffset + 6); - this.contents[codeAttributeOffset + 2] = (byte) (codeAttributeLength >> 24); - this.contents[codeAttributeOffset + 3] = (byte) (codeAttributeLength >> 16); - this.contents[codeAttributeOffset + 4] = (byte) (codeAttributeLength >> 8); - this.contents[codeAttributeOffset + 5] = (byte) codeAttributeLength; - } - - /** - * INTERNAL USE-ONLY - * That method completes the creation of the code attribute by setting - * - the attribute_length - * - max_stack - * - max_locals - * - code_length - * - exception table - * - and debug attributes if necessary. - * - * @param binding org.aspectj.org.eclipse.jdt.internal.compiler.lookup.SyntheticAccessMethodBinding - * @param codeAttributeOffset <CODE>int</CODE> - */ - public void completeCodeAttributeForSyntheticMethod( - SyntheticMethodBinding binding, - int codeAttributeOffset, - int[] startLineIndexes) { - - this.completeCodeAttributeForSyntheticMethod( - false, - binding, - codeAttributeOffset, - startLineIndexes); - } - - private void completeArgumentAnnotationInfo(Argument[] arguments, List allAnnotationContexts) { - for (int i = 0, max = arguments.length; i < max; i++) { - Argument argument = arguments[i]; - if ((argument.bits & ASTNode.HasTypeAnnotations) != 0) { - argument.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER, i, allAnnotationContexts); - } - } - } - - /** - * INTERNAL USE-ONLY - * Complete the creation of a method info by setting up the number of attributes at the right offset. - * - * @param methodAttributeOffset <CODE>int</CODE> - * @param attributesNumber <CODE>int</CODE> - */ - public void completeMethodInfo( - MethodBinding binding, - int methodAttributeOffset, - int attributesNumber) { - - if ((this.produceAttributes & ClassFileConstants.ATTR_TYPE_ANNOTATION) != 0) { - List allTypeAnnotationContexts = new ArrayList(); - int invisibleTypeAnnotationsCounter = 0; - int visibleTypeAnnotationsCounter = 0; - AbstractMethodDeclaration methodDeclaration = binding.sourceMethod(); - if (methodDeclaration != null) { - if ((methodDeclaration.bits & ASTNode.HasTypeAnnotations) != 0) { - Argument[] arguments = methodDeclaration.arguments; - if (arguments != null) { - completeArgumentAnnotationInfo(arguments, allTypeAnnotationContexts); - } - Receiver receiver = methodDeclaration.receiver; - if (receiver != null && (receiver.type.bits & ASTNode.HasTypeAnnotations) != 0) { - receiver.type.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RECEIVER, allTypeAnnotationContexts); - } - } - Annotation[] annotations = methodDeclaration.annotations; - if (annotations != null && !methodDeclaration.isClinit() && (methodDeclaration.isConstructor() || binding.returnType.id != T_void)) { - methodDeclaration.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RETURN, allTypeAnnotationContexts); - } - if (!methodDeclaration.isConstructor() && !methodDeclaration.isClinit() && binding.returnType.id != T_void) { - MethodDeclaration declaration = (MethodDeclaration) methodDeclaration; - TypeReference typeReference = declaration.returnType; - if ((typeReference.bits & ASTNode.HasTypeAnnotations) != 0) { - typeReference.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_RETURN, allTypeAnnotationContexts); - } - } - TypeReference[] thrownExceptions = methodDeclaration.thrownExceptions; - if (thrownExceptions != null) { - for (int i = 0, max = thrownExceptions.length; i < max; i++) { - TypeReference thrownException = thrownExceptions[i]; - thrownException.getAllAnnotationContexts(AnnotationTargetTypeConstants.THROWS, i, allTypeAnnotationContexts); - } - } - TypeParameter[] typeParameters = methodDeclaration.typeParameters(); - if (typeParameters != null) { - for (int i = 0, max = typeParameters.length; i < max; i++) { - TypeParameter typeParameter = typeParameters[i]; - if ((typeParameter.bits & ASTNode.HasTypeAnnotations) != 0) { - typeParameter.getAllAnnotationContexts(AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER, i, allTypeAnnotationContexts); - } - } - } - } else if (binding.sourceLambda() != null) { // SyntheticMethodBinding, purpose : LambdaMethod. - LambdaExpression lambda = binding.sourceLambda(); - if ((lambda.bits & ASTNode.HasTypeAnnotations) != 0) { - if (lambda.arguments != null) - completeArgumentAnnotationInfo(lambda.arguments, allTypeAnnotationContexts); - } - } - int size = allTypeAnnotationContexts.size(); - if (size != 0) { - AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size]; - allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray); - for (int j = 0, max2 = allTypeAnnotationContextsArray.length; j < max2; j++) { - AnnotationContext annotationContext = allTypeAnnotationContextsArray[j]; - if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) { - invisibleTypeAnnotationsCounter++; - } else { - visibleTypeAnnotationsCounter++; - } - } - attributesNumber += generateRuntimeTypeAnnotations( - allTypeAnnotationContextsArray, - visibleTypeAnnotationsCounter, - invisibleTypeAnnotationsCounter); - } - } - if ((this.produceAttributes & ClassFileConstants.ATTR_METHOD_PARAMETERS) != 0) { - attributesNumber += generateMethodParameters(binding); - } - // update the number of attributes - this.contents[methodAttributeOffset++] = (byte) (attributesNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributesNumber; - } - - private void dumpLocations(int[] locations) { - if (locations == null) { - // no type path - if (this.contentsOffset + 1 >= this.contents.length) { - resizeContents(1); - } - this.contents[this.contentsOffset++] = (byte) 0; - } else { - int length = locations.length; - if (this.contentsOffset + length >= this.contents.length) { - resizeContents(length + 1); - } - this.contents[this.contentsOffset++] = (byte) (locations.length / 2); - for (int i = 0; i < length; i++) { - this.contents[this.contentsOffset++] = (byte) locations[i]; - } - } - } - private void dumpTargetTypeContents(int targetType, AnnotationContext annotationContext) { - switch(targetType) { - case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER : - case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER : - // parameter index - this.contents[this.contentsOffset++] = (byte) annotationContext.info; - break; - - case AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER_BOUND : - // type_parameter_index - this.contents[this.contentsOffset++] = (byte) annotationContext.info; - // bound_index - this.contents[this.contentsOffset++] = (byte) annotationContext.info2; - break; - case AnnotationTargetTypeConstants.FIELD : - case AnnotationTargetTypeConstants.METHOD_RECEIVER : - case AnnotationTargetTypeConstants.METHOD_RETURN : - // target_info is empty_target - break; - case AnnotationTargetTypeConstants.METHOD_FORMAL_PARAMETER : - // target_info is parameter index - this.contents[this.contentsOffset++] = (byte) annotationContext.info; - break; - - case AnnotationTargetTypeConstants.INSTANCEOF : - case AnnotationTargetTypeConstants.NEW : - case AnnotationTargetTypeConstants.EXCEPTION_PARAMETER : - case AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE : - case AnnotationTargetTypeConstants.METHOD_REFERENCE : - // bytecode offset for new/instanceof/method_reference - // exception table entry index for exception_parameter - this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8); - this.contents[this.contentsOffset++] = (byte) annotationContext.info; - break; - case AnnotationTargetTypeConstants.CAST : - // bytecode offset - this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8); - this.contents[this.contentsOffset++] = (byte) annotationContext.info; - this.contents[this.contentsOffset++] = (byte) annotationContext.info2; - break; - - case AnnotationTargetTypeConstants.CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT : - case AnnotationTargetTypeConstants.METHOD_INVOCATION_TYPE_ARGUMENT : - case AnnotationTargetTypeConstants.CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT : - case AnnotationTargetTypeConstants.METHOD_REFERENCE_TYPE_ARGUMENT : - // bytecode offset - this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8); - this.contents[this.contentsOffset++] = (byte) annotationContext.info; - // type_argument_index - this.contents[this.contentsOffset++] = (byte) annotationContext.info2; - break; - - case AnnotationTargetTypeConstants.CLASS_EXTENDS : - case AnnotationTargetTypeConstants.THROWS : - // For CLASS_EXTENDS - info is supertype index (-1 = superclass) - // For THROWS - info is exception table index - this.contents[this.contentsOffset++] = (byte) (annotationContext.info >> 8); - this.contents[this.contentsOffset++] = (byte) annotationContext.info; - break; - - case AnnotationTargetTypeConstants.LOCAL_VARIABLE : - case AnnotationTargetTypeConstants.RESOURCE_VARIABLE : - int localVariableTableOffset = this.contentsOffset; - LocalVariableBinding localVariable = annotationContext.variableBinding; - int actualSize = 0; - int initializationCount = localVariable.initializationCount; - actualSize += 6 * initializationCount; - // reserve enough space - if (this.contentsOffset + actualSize >= this.contents.length) { - resizeContents(actualSize); - } - this.contentsOffset += 2; - int numberOfEntries = 0; - for (int j = 0; j < initializationCount; j++) { - int startPC = localVariable.initializationPCs[j << 1]; - int endPC = localVariable.initializationPCs[(j << 1) + 1]; - if (startPC != endPC) { // only entries for non zero length - // now we can safely add the local entry - numberOfEntries++; - this.contents[this.contentsOffset++] = (byte) (startPC >> 8); - this.contents[this.contentsOffset++] = (byte) startPC; - int length = endPC - startPC; - this.contents[this.contentsOffset++] = (byte) (length >> 8); - this.contents[this.contentsOffset++] = (byte) length; - int resolvedPosition = localVariable.resolvedPosition; - this.contents[this.contentsOffset++] = (byte) (resolvedPosition >> 8); - this.contents[this.contentsOffset++] = (byte) resolvedPosition; - } - } - this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8); - this.contents[localVariableTableOffset] = (byte) numberOfEntries; - break; - case AnnotationTargetTypeConstants.METHOD_TYPE_PARAMETER_BOUND : - this.contents[this.contentsOffset++] = (byte) annotationContext.info; - this.contents[this.contentsOffset++] = (byte) annotationContext.info2; - break; - } - } - - - - /** - * INTERNAL USE-ONLY - * This methods returns a char[] representing the file name of the receiver - * - * @return char[] - */ - public char[] fileName() { - return this.constantPool.UTF8Cache.returnKeyFor(2); - } - - private void generateAnnotation(Annotation annotation, int currentOffset) { - int startingContentsOffset = currentOffset; - if (this.contentsOffset + 4 >= this.contents.length) { - resizeContents(4); - } - TypeBinding annotationTypeBinding = annotation.resolvedType; - if (annotationTypeBinding == null) { - this.contentsOffset = startingContentsOffset; - return; - } - if (annotationTypeBinding.isMemberType()) { - this.recordInnerClasses(annotationTypeBinding); - } - final int typeIndex = this.constantPool.literalIndex(annotationTypeBinding.signature()); - this.contents[this.contentsOffset++] = (byte) (typeIndex >> 8); - this.contents[this.contentsOffset++] = (byte) typeIndex; - if (annotation instanceof NormalAnnotation) { - NormalAnnotation normalAnnotation = (NormalAnnotation) annotation; - MemberValuePair[] memberValuePairs = normalAnnotation.memberValuePairs; - int memberValuePairOffset = this.contentsOffset; - if (memberValuePairs != null) { - int memberValuePairsCount = 0; - int memberValuePairsLengthPosition = this.contentsOffset; - this.contentsOffset+=2; // leave space to fill in the pair count later - int resetPosition = this.contentsOffset; - final int memberValuePairsLength = memberValuePairs.length; - loop: for (int i = 0; i < memberValuePairsLength; i++) { - MemberValuePair memberValuePair = memberValuePairs[i]; - if (this.contentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - final int elementNameIndex = this.constantPool.literalIndex(memberValuePair.name); - this.contents[this.contentsOffset++] = (byte) (elementNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) elementNameIndex; - MethodBinding methodBinding = memberValuePair.binding; - if (methodBinding == null) { - this.contentsOffset = resetPosition; - } else { - try { - generateElementValue(memberValuePair.value, methodBinding.returnType, startingContentsOffset); - if (this.contentsOffset == memberValuePairOffset) { - // ignore all annotation values -// this.contentsOffset = resetPosition; - this.contents[this.contentsOffset++]=0; - this.contents[this.contentsOffset++]=0; - break loop; - } - memberValuePairsCount++; - resetPosition = this.contentsOffset; - } catch(ClassCastException e) { - this.contentsOffset = resetPosition; - } catch(ShouldNotImplement e) { - this.contentsOffset = resetPosition; - } - } - } - this.contents[memberValuePairsLengthPosition++] = (byte) (memberValuePairsCount >> 8); - this.contents[memberValuePairsLengthPosition++] = (byte) memberValuePairsCount; - } else { - this.contents[this.contentsOffset++] = 0; - this.contents[this.contentsOffset++] = 0; - } - } else if (annotation instanceof SingleMemberAnnotation) { - SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation; - // this is a single member annotation (one member value) - int memberValuePairCount = 0; // will not get to 1 if there is a problem with the annotation value - int memberValuePairLengthPosition = this.contentsOffset; - this.contentsOffset+=2;// leave space to fill in the pair count later - if (this.contentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - final int elementNameIndex = this.constantPool.literalIndex(VALUE); - int resetPosition = this.contentsOffset; - this.contents[this.contentsOffset++] = (byte) (elementNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) elementNameIndex; - MethodBinding methodBinding = singleMemberAnnotation.memberValuePairs()[0].binding; - if (methodBinding == null) { - this.contentsOffset = resetPosition; - } else { - int memberValuePairOffset = this.contentsOffset; - try { - generateElementValue(singleMemberAnnotation.memberValue, methodBinding.returnType, memberValuePairOffset); - if (this.contentsOffset == memberValuePairOffset) { - // ignore annotation value - this.contentsOffset = resetPosition; - } else { - memberValuePairCount++; - resetPosition = this.contentsOffset; - } - } catch(ClassCastException e) { - this.contentsOffset = resetPosition; - } catch(ShouldNotImplement e) { - this.contentsOffset = resetPosition; - } - } - this.contents[memberValuePairLengthPosition++] = (byte) (memberValuePairCount >> 8); - this.contents[memberValuePairLengthPosition++] = (byte) memberValuePairCount; - } else { - // this is a marker annotation (no member value pairs) - this.contents[this.contentsOffset++] = 0; - this.contents[this.contentsOffset++] = 0; - } - } - - private int generateAnnotationDefaultAttribute(AnnotationMethodDeclaration declaration, int attributeOffset) { - int attributesNumber = 0; - // add an annotation default attribute - int annotationDefaultNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.AnnotationDefaultName); - if (this.contentsOffset + 6 >= this.contents.length) { - resizeContents(6); - } - this.contents[this.contentsOffset++] = (byte) (annotationDefaultNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) annotationDefaultNameIndex; - int attributeLengthOffset = this.contentsOffset; - this.contentsOffset += 4; - generateElementValue(declaration.defaultValue, declaration.binding.returnType, attributeOffset); - if (this.contentsOffset != attributeOffset) { - int attributeLength = this.contentsOffset - attributeLengthOffset - 4; - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8); - this.contents[attributeLengthOffset++] = (byte) attributeLength; - attributesNumber++; - } - return attributesNumber; - } - /** - * INTERNAL USE-ONLY - * That method generates the header of a code attribute. - * - the index inside the constant pool for the attribute name ("Code") - * - leave some space for attribute_length(4), max_stack(2), max_locals(2), code_length(4). - */ - public void generateCodeAttributeHeader() { - if (this.contentsOffset + 20 >= this.contents.length) { - resizeContents(20); - } - int constantValueNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.CodeName); - this.contents[this.contentsOffset++] = (byte) (constantValueNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) constantValueNameIndex; - // leave space for attribute_length(4), max_stack(2), max_locals(2), code_length(4) - this.contentsOffset += 12; - } - - private int generateConstantValueAttribute(Constant fieldConstant, FieldBinding fieldBinding, int fieldAttributeOffset) { - int localContentsOffset = this.contentsOffset; - int attributesNumber = 1; - if (localContentsOffset + 8 >= this.contents.length) { - resizeContents(8); - } - // Now we generate the constant attribute corresponding to the fieldBinding - int constantValueNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.ConstantValueName); - this.contents[localContentsOffset++] = (byte) (constantValueNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) constantValueNameIndex; - // The attribute length = 2 in case of a constantValue attribute - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 2; - // Need to add the constant_value_index - switch (fieldConstant.typeID()) { - case T_boolean : - int booleanValueIndex = - this.constantPool.literalIndex(fieldConstant.booleanValue() ? 1 : 0); - this.contents[localContentsOffset++] = (byte) (booleanValueIndex >> 8); - this.contents[localContentsOffset++] = (byte) booleanValueIndex; - break; - case T_byte : - case T_char : - case T_int : - case T_short : - int integerValueIndex = - this.constantPool.literalIndex(fieldConstant.intValue()); - this.contents[localContentsOffset++] = (byte) (integerValueIndex >> 8); - this.contents[localContentsOffset++] = (byte) integerValueIndex; - break; - case T_float : - int floatValueIndex = - this.constantPool.literalIndex(fieldConstant.floatValue()); - this.contents[localContentsOffset++] = (byte) (floatValueIndex >> 8); - this.contents[localContentsOffset++] = (byte) floatValueIndex; - break; - case T_double : - int doubleValueIndex = - this.constantPool.literalIndex(fieldConstant.doubleValue()); - this.contents[localContentsOffset++] = (byte) (doubleValueIndex >> 8); - this.contents[localContentsOffset++] = (byte) doubleValueIndex; - break; - case T_long : - int longValueIndex = - this.constantPool.literalIndex(fieldConstant.longValue()); - this.contents[localContentsOffset++] = (byte) (longValueIndex >> 8); - this.contents[localContentsOffset++] = (byte) longValueIndex; - break; - case T_JavaLangString : - int stringValueIndex = - this.constantPool.literalIndex( - ((StringConstant) fieldConstant).stringValue()); - if (stringValueIndex == -1) { - if (!this.creatingProblemType) { - // report an error and abort: will lead to a problem type classfile creation - TypeDeclaration typeDeclaration = this.referenceBinding.scope.referenceContext; - FieldDeclaration[] fieldDecls = typeDeclaration.fields; - int max = fieldDecls == null ? 0 : fieldDecls.length; - for (int i = 0; i < max; i++) { - if (fieldDecls[i].binding == fieldBinding) { - // problem should abort - typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit( - fieldDecls[i]); - } - } - } else { - // already inside a problem type creation : no constant for this field - this.contentsOffset = fieldAttributeOffset; - attributesNumber = 0; - } - } else { - this.contents[localContentsOffset++] = (byte) (stringValueIndex >> 8); - this.contents[localContentsOffset++] = (byte) stringValueIndex; - } - } - this.contentsOffset = localContentsOffset; - return attributesNumber; - } - private int generateDeprecatedAttribute() { - int localContentsOffset = this.contentsOffset; - if (localContentsOffset + 6 >= this.contents.length) { - resizeContents(6); - } - int deprecatedAttributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.DeprecatedName); - this.contents[localContentsOffset++] = (byte) (deprecatedAttributeNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) deprecatedAttributeNameIndex; - // the length of a deprecated attribute is equals to 0 - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contentsOffset = localContentsOffset; - return 1; - } - private void generateElementValue( - Expression defaultValue, - TypeBinding memberValuePairReturnType, - int attributeOffset) { - Constant constant = defaultValue.constant; - TypeBinding defaultValueBinding = defaultValue.resolvedType; - if (defaultValueBinding == null) { - this.contentsOffset = attributeOffset; - } else { - if (defaultValueBinding.isMemberType()) { - this.recordInnerClasses(defaultValueBinding); - } - if (memberValuePairReturnType.isMemberType()) { - this.recordInnerClasses(memberValuePairReturnType); - } - if (memberValuePairReturnType.isArrayType() && !defaultValueBinding.isArrayType()) { - // automatic wrapping - if (this.contentsOffset + 3 >= this.contents.length) { - resizeContents(3); - } - this.contents[this.contentsOffset++] = (byte) '['; - this.contents[this.contentsOffset++] = (byte) 0; - this.contents[this.contentsOffset++] = (byte) 1; - } - if (constant != null && constant != Constant.NotAConstant) { - generateElementValue(attributeOffset, defaultValue, constant, memberValuePairReturnType.leafComponentType()); - } else { - generateElementValueForNonConstantExpression(defaultValue, attributeOffset, defaultValueBinding); - } - } - } - /** - * @param attributeOffset - */ - private void generateElementValue(int attributeOffset, Expression defaultValue, Constant constant, TypeBinding binding) { - if (this.contentsOffset + 3 >= this.contents.length) { - resizeContents(3); - } - switch (binding.id) { - case T_boolean : - this.contents[this.contentsOffset++] = (byte) 'Z'; - int booleanValueIndex = - this.constantPool.literalIndex(constant.booleanValue() ? 1 : 0); - this.contents[this.contentsOffset++] = (byte) (booleanValueIndex >> 8); - this.contents[this.contentsOffset++] = (byte) booleanValueIndex; - break; - case T_byte : - this.contents[this.contentsOffset++] = (byte) 'B'; - int integerValueIndex = - this.constantPool.literalIndex(constant.intValue()); - this.contents[this.contentsOffset++] = (byte) (integerValueIndex >> 8); - this.contents[this.contentsOffset++] = (byte) integerValueIndex; - break; - case T_char : - this.contents[this.contentsOffset++] = (byte) 'C'; - integerValueIndex = - this.constantPool.literalIndex(constant.intValue()); - this.contents[this.contentsOffset++] = (byte) (integerValueIndex >> 8); - this.contents[this.contentsOffset++] = (byte) integerValueIndex; - break; - case T_int : - this.contents[this.contentsOffset++] = (byte) 'I'; - integerValueIndex = - this.constantPool.literalIndex(constant.intValue()); - this.contents[this.contentsOffset++] = (byte) (integerValueIndex >> 8); - this.contents[this.contentsOffset++] = (byte) integerValueIndex; - break; - case T_short : - this.contents[this.contentsOffset++] = (byte) 'S'; - integerValueIndex = - this.constantPool.literalIndex(constant.intValue()); - this.contents[this.contentsOffset++] = (byte) (integerValueIndex >> 8); - this.contents[this.contentsOffset++] = (byte) integerValueIndex; - break; - case T_float : - this.contents[this.contentsOffset++] = (byte) 'F'; - int floatValueIndex = - this.constantPool.literalIndex(constant.floatValue()); - this.contents[this.contentsOffset++] = (byte) (floatValueIndex >> 8); - this.contents[this.contentsOffset++] = (byte) floatValueIndex; - break; - case T_double : - this.contents[this.contentsOffset++] = (byte) 'D'; - int doubleValueIndex = - this.constantPool.literalIndex(constant.doubleValue()); - this.contents[this.contentsOffset++] = (byte) (doubleValueIndex >> 8); - this.contents[this.contentsOffset++] = (byte) doubleValueIndex; - break; - case T_long : - this.contents[this.contentsOffset++] = (byte) 'J'; - int longValueIndex = - this.constantPool.literalIndex(constant.longValue()); - this.contents[this.contentsOffset++] = (byte) (longValueIndex >> 8); - this.contents[this.contentsOffset++] = (byte) longValueIndex; - break; - case T_JavaLangString : - this.contents[this.contentsOffset++] = (byte) 's'; - int stringValueIndex = - this.constantPool.literalIndex(((StringConstant) constant).stringValue().toCharArray()); - if (stringValueIndex == -1) { - if (!this.creatingProblemType) { - // report an error and abort: will lead to a problem type classfile creation - TypeDeclaration typeDeclaration = this.referenceBinding.scope.referenceContext; - typeDeclaration.scope.problemReporter().stringConstantIsExceedingUtf8Limit(defaultValue); - } else { - // already inside a problem type creation : no attribute - this.contentsOffset = attributeOffset; - } - } else { - this.contents[this.contentsOffset++] = (byte) (stringValueIndex >> 8); - this.contents[this.contentsOffset++] = (byte) stringValueIndex; - } - } - } - - private void generateElementValueForNonConstantExpression(Expression defaultValue, int attributeOffset, TypeBinding defaultValueBinding) { - if (defaultValueBinding != null) { - if (defaultValueBinding.isEnum()) { - if (this.contentsOffset + 5 >= this.contents.length) { - resizeContents(5); - } - this.contents[this.contentsOffset++] = (byte) 'e'; - FieldBinding fieldBinding = null; - if (defaultValue instanceof QualifiedNameReference) { - QualifiedNameReference nameReference = (QualifiedNameReference) defaultValue; - fieldBinding = (FieldBinding) nameReference.binding; - } else if (defaultValue instanceof SingleNameReference) { - SingleNameReference nameReference = (SingleNameReference) defaultValue; - fieldBinding = (FieldBinding) nameReference.binding; - } else { - this.contentsOffset = attributeOffset; - } - if (fieldBinding != null) { - final int enumConstantTypeNameIndex = this.constantPool.literalIndex(fieldBinding.type.signature()); - final int enumConstantNameIndex = this.constantPool.literalIndex(fieldBinding.name); - this.contents[this.contentsOffset++] = (byte) (enumConstantTypeNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) enumConstantTypeNameIndex; - this.contents[this.contentsOffset++] = (byte) (enumConstantNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) enumConstantNameIndex; - } - } else if (defaultValueBinding.isAnnotationType()) { - if (this.contentsOffset + 1 >= this.contents.length) { - resizeContents(1); - } - this.contents[this.contentsOffset++] = (byte) '@'; - generateAnnotation((Annotation) defaultValue, attributeOffset); - } else if (defaultValueBinding.isArrayType()) { - // array type - if (this.contentsOffset + 3 >= this.contents.length) { - resizeContents(3); - } - this.contents[this.contentsOffset++] = (byte) '['; - if (defaultValue instanceof ArrayInitializer) { - ArrayInitializer arrayInitializer = (ArrayInitializer) defaultValue; - int arrayLength = arrayInitializer.expressions != null ? arrayInitializer.expressions.length : 0; - this.contents[this.contentsOffset++] = (byte) (arrayLength >> 8); - this.contents[this.contentsOffset++] = (byte) arrayLength; - for (int i = 0; i < arrayLength; i++) { - generateElementValue(arrayInitializer.expressions[i], defaultValueBinding.leafComponentType(), attributeOffset); - } - } else { - this.contentsOffset = attributeOffset; - } - } else { - // class type - if (this.contentsOffset + 3 >= this.contents.length) { - resizeContents(3); - } - this.contents[this.contentsOffset++] = (byte) 'c'; - if (defaultValue instanceof ClassLiteralAccess) { - ClassLiteralAccess classLiteralAccess = (ClassLiteralAccess) defaultValue; - final int classInfoIndex = this.constantPool.literalIndex(classLiteralAccess.targetType.signature()); - this.contents[this.contentsOffset++] = (byte) (classInfoIndex >> 8); - this.contents[this.contentsOffset++] = (byte) classInfoIndex; - } else { - this.contentsOffset = attributeOffset; - } - } - } else { - this.contentsOffset = attributeOffset; - } - } - - private int generateEnclosingMethodAttribute() { - int localContentsOffset = this.contentsOffset; - // add enclosing method attribute (1.5 mode only) - if (localContentsOffset + 10 >= this.contents.length) { - resizeContents(10); - } - int enclosingMethodAttributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.EnclosingMethodName); - this.contents[localContentsOffset++] = (byte) (enclosingMethodAttributeNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) enclosingMethodAttributeNameIndex; - // the length of a signature attribute is equals to 2 - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 4; - - int enclosingTypeIndex = this.constantPool.literalIndexForType(this.referenceBinding.enclosingType().constantPoolName()); - this.contents[localContentsOffset++] = (byte) (enclosingTypeIndex >> 8); - this.contents[localContentsOffset++] = (byte) enclosingTypeIndex; - byte methodIndexByte1 = 0; - byte methodIndexByte2 = 0; - if (this.referenceBinding instanceof LocalTypeBinding) { - MethodBinding methodBinding = ((LocalTypeBinding) this.referenceBinding).enclosingMethod; - if (methodBinding != null) { - int enclosingMethodIndex = this.constantPool.literalIndexForNameAndType(methodBinding.selector, methodBinding.signature(this)); - methodIndexByte1 = (byte) (enclosingMethodIndex >> 8); - methodIndexByte2 = (byte) enclosingMethodIndex; - } - } - this.contents[localContentsOffset++] = methodIndexByte1; - this.contents[localContentsOffset++] = methodIndexByte2; - this.contentsOffset = localContentsOffset; - return 1; - } - private int generateExceptionsAttribute(ReferenceBinding[] thrownsExceptions) { - int localContentsOffset = this.contentsOffset; - int length = thrownsExceptions.length; - int exSize = 8 + length * 2; - if (exSize + this.contentsOffset >= this.contents.length) { - resizeContents(exSize); - } - int exceptionNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.ExceptionsName); - this.contents[localContentsOffset++] = (byte) (exceptionNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) exceptionNameIndex; - // The attribute length = length * 2 + 2 in case of a exception attribute - int attributeLength = length * 2 + 2; - this.contents[localContentsOffset++] = (byte) (attributeLength >> 24); - this.contents[localContentsOffset++] = (byte) (attributeLength >> 16); - this.contents[localContentsOffset++] = (byte) (attributeLength >> 8); - this.contents[localContentsOffset++] = (byte) attributeLength; - this.contents[localContentsOffset++] = (byte) (length >> 8); - this.contents[localContentsOffset++] = (byte) length; - for (int i = 0; i < length; i++) { - int exceptionIndex = this.constantPool.literalIndexForType(thrownsExceptions[i]); - this.contents[localContentsOffset++] = (byte) (exceptionIndex >> 8); - this.contents[localContentsOffset++] = (byte) exceptionIndex; - } - this.contentsOffset = localContentsOffset; - return 1; - } - private int generateHierarchyInconsistentAttribute() { - int localContentsOffset = this.contentsOffset; - // add an attribute for inconsistent hierarchy - if (localContentsOffset + 6 >= this.contents.length) { - resizeContents(6); - } - int inconsistentHierarchyNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.InconsistentHierarchy); - this.contents[localContentsOffset++] = (byte) (inconsistentHierarchyNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) inconsistentHierarchyNameIndex; - // the length of an inconsistent hierarchy attribute is equals to 0 - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contentsOffset = localContentsOffset; - return 1; - } - private int generateInnerClassAttribute(int numberOfInnerClasses, ReferenceBinding[] innerClasses) { - int localContentsOffset = this.contentsOffset; - // Generate the inner class attribute - int exSize = 8 * numberOfInnerClasses + 8; - if (exSize + localContentsOffset >= this.contents.length) { - resizeContents(exSize); - } - // Now we now the size of the attribute and the number of entries - // attribute name - int attributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.InnerClassName); - this.contents[localContentsOffset++] = (byte) (attributeNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) attributeNameIndex; - int value = (numberOfInnerClasses << 3) + 2; - this.contents[localContentsOffset++] = (byte) (value >> 24); - this.contents[localContentsOffset++] = (byte) (value >> 16); - this.contents[localContentsOffset++] = (byte) (value >> 8); - this.contents[localContentsOffset++] = (byte) value; - this.contents[localContentsOffset++] = (byte) (numberOfInnerClasses >> 8); - this.contents[localContentsOffset++] = (byte) numberOfInnerClasses; - for (int i = 0; i < numberOfInnerClasses; i++) { - ReferenceBinding innerClass = innerClasses[i]; - int accessFlags = innerClass.getAccessFlags(); - int innerClassIndex = this.constantPool.literalIndexForType(innerClass.constantPoolName()); - // inner class index - this.contents[localContentsOffset++] = (byte) (innerClassIndex >> 8); - this.contents[localContentsOffset++] = (byte) innerClassIndex; - // outer class index: anonymous and local have no outer class index - if (innerClass.isMemberType()) { - // member or member of local - int outerClassIndex = this.constantPool.literalIndexForType(innerClass.enclosingType().constantPoolName()); - this.contents[localContentsOffset++] = (byte) (outerClassIndex >> 8); - this.contents[localContentsOffset++] = (byte) outerClassIndex; - } else { - // equals to 0 if the innerClass is not a member type - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - } - // name index - if (!innerClass.isAnonymousType()) { - int nameIndex = this.constantPool.literalIndex(innerClass.sourceName()); - this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); - this.contents[localContentsOffset++] = (byte) nameIndex; - } else { - // equals to 0 if the innerClass is an anonymous type - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - } - // access flag - if (innerClass.isAnonymousType()) { - accessFlags &= ~ClassFileConstants.AccFinal; - } else if (innerClass.isMemberType() && innerClass.isInterface()) { - accessFlags |= ClassFileConstants.AccStatic; // implicitely static - } - this.contents[localContentsOffset++] = (byte) (accessFlags >> 8); - this.contents[localContentsOffset++] = (byte) accessFlags; - } - this.contentsOffset = localContentsOffset; - return 1; - } - - private int generateBootstrapMethods(List functionalExpressionList) { - /* See JVM spec 4.7.21 - The BootstrapMethods attribute has the following format: - BootstrapMethods_attribute { - u2 attribute_name_index; - u4 attribute_length; - u2 num_bootstrap_methods; - { u2 bootstrap_method_ref; - u2 num_bootstrap_arguments; - u2 bootstrap_arguments[num_bootstrap_arguments]; - } bootstrap_methods[num_bootstrap_methods]; - } - */ - // Record inner classes for MethodHandles$Lookup - ReferenceBinding methodHandlesLookup = this.referenceBinding.scope.getJavaLangInvokeMethodHandlesLookup(); - if (methodHandlesLookup == null) return 0; // skip bootstrap section, class path problem already reported, just avoid NPE. - recordInnerClasses(methodHandlesLookup); // Should be done, it's what javac does also - ReferenceBinding javaLangInvokeLambdaMetafactory = this.referenceBinding.scope.getJavaLangInvokeLambdaMetafactory(); - - // Depending on the complexity of the expression it may be necessary to use the altMetafactory() rather than the metafactory() - int indexForMetaFactory = 0; - int indexForAltMetaFactory = 0; - - int numberOfBootstraps = functionalExpressionList.size(); - int localContentsOffset = this.contentsOffset; - // Generate the boot strap attribute - since we are only making lambdas and - // functional expressions, we know the size ahead of time - this less general - // than the full invokedynamic scope, but fine for Java 8 - - final int contentsEntries = 10; - int exSize = contentsEntries * numberOfBootstraps + 8; - if (exSize + localContentsOffset >= this.contents.length) { - resizeContents(exSize); - } - - int attributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.BootstrapMethodsName); - this.contents[localContentsOffset++] = (byte) (attributeNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) attributeNameIndex; - // leave space for attribute_length and remember where to insert it - int attributeLengthPosition = localContentsOffset; - localContentsOffset += 4; - this.contents[localContentsOffset++] = (byte) (numberOfBootstraps >> 8); - this.contents[localContentsOffset++] = (byte) numberOfBootstraps; - for (int i = 0; i < numberOfBootstraps; i++) { - FunctionalExpression functional = (FunctionalExpression) functionalExpressionList.get(i); - MethodBinding [] bridges = functional.getRequiredBridges(); - TypeBinding[] markerInterfaces = null; - if (functional instanceof LambdaExpression && - (((markerInterfaces=((LambdaExpression)functional).getMarkerInterfaces()) != null) || - ((LambdaExpression)functional).isSerializable) || - bridges != null) { - - LambdaExpression lambdaEx = (LambdaExpression)functional; - // may need even more space - int extraSpace = 2; // at least 2 more than when the normal metafactory is used, for the bitflags entry - if (markerInterfaces != null) { - // 2 for the marker interface list size then 2 per marker interface index - extraSpace += (2 + 2 * markerInterfaces.length); - } - if (bridges != null) { - // 2 for bridge count then 2 per bridge method type. - extraSpace += (2 + 2 * bridges.length); - } - if (extraSpace + contentsEntries + localContentsOffset >= this.contents.length) { - resizeContents(extraSpace + contentsEntries); - } - - if (indexForAltMetaFactory == 0) { - indexForAltMetaFactory = - this.constantPool.literalIndexForMethodHandle(ClassFileConstants.MethodHandleRefKindInvokeStatic, javaLangInvokeLambdaMetafactory, - ConstantPool.ALTMETAFACTORY, ConstantPool.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY_ALTMETAFACTORY_SIGNATURE, false); - } - this.contents[localContentsOffset++] = (byte) (indexForAltMetaFactory >> 8); - this.contents[localContentsOffset++] = (byte) indexForAltMetaFactory; - - // u2 num_bootstrap_arguments - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = (byte) (4 + (markerInterfaces==null?0:1+markerInterfaces.length) + - (bridges == null ? 0 : 1 + bridges.length)); - - int functionalDescriptorIndex = this.constantPool.literalIndexForMethodType(functional.descriptor.original().signature()); - this.contents[localContentsOffset++] = (byte) (functionalDescriptorIndex >> 8); - this.contents[localContentsOffset++] = (byte) functionalDescriptorIndex; - - int methodHandleIndex = this.constantPool.literalIndexForMethodHandle(functional.binding.original()); // Speak of " implementation" (erased) version here, adaptations described below. - this.contents[localContentsOffset++] = (byte) (methodHandleIndex >> 8); - this.contents[localContentsOffset++] = (byte) methodHandleIndex; - - char [] instantiatedSignature = functional.descriptor.signature(); - int methodTypeIndex = this.constantPool.literalIndexForMethodType(instantiatedSignature); - this.contents[localContentsOffset++] = (byte) (methodTypeIndex >> 8); - this.contents[localContentsOffset++] = (byte) methodTypeIndex; - - int bitflags = 0; - if (lambdaEx.isSerializable) { - bitflags |= ClassFileConstants.FLAG_SERIALIZABLE; - } - if (markerInterfaces!=null) { - bitflags |= ClassFileConstants.FLAG_MARKERS; - } - if (bridges != null) { - bitflags |= ClassFileConstants.FLAG_BRIDGES; - } - int indexForBitflags = this.constantPool.literalIndex(bitflags); - - this.contents[localContentsOffset++] = (byte)(indexForBitflags>>8); - this.contents[localContentsOffset++] = (byte)(indexForBitflags); - - if (markerInterfaces != null) { - int markerInterfaceCountIndex = this.constantPool.literalIndex(markerInterfaces.length); - this.contents[localContentsOffset++] = (byte)(markerInterfaceCountIndex>>8); - this.contents[localContentsOffset++] = (byte)(markerInterfaceCountIndex); - for (int m = 0, maxm = markerInterfaces.length; m < maxm; m++) { - int classTypeIndex = this.constantPool.literalIndexForType(markerInterfaces[m]); - this.contents[localContentsOffset++] = (byte)(classTypeIndex>>8); - this.contents[localContentsOffset++] = (byte)(classTypeIndex); - } - } - if (bridges != null) { - int bridgeCountIndex = this.constantPool.literalIndex(bridges.length); - this.contents[localContentsOffset++] = (byte) (bridgeCountIndex >> 8); - this.contents[localContentsOffset++] = (byte) (bridgeCountIndex); - for (int m = 0, maxm = bridges.length; m < maxm; m++) { - char [] bridgeSignature = bridges[m].signature(); - int bridgeMethodTypeIndex = this.constantPool.literalIndexForMethodType(bridgeSignature); - this.contents[localContentsOffset++] = (byte) (bridgeMethodTypeIndex >> 8); - this.contents[localContentsOffset++] = (byte) bridgeMethodTypeIndex; - } - } - } else { - if (indexForMetaFactory == 0) { - indexForMetaFactory = this.constantPool.literalIndexForMethodHandle(ClassFileConstants.MethodHandleRefKindInvokeStatic, javaLangInvokeLambdaMetafactory, - ConstantPool.METAFACTORY, ConstantPool.JAVA_LANG_INVOKE_LAMBDAMETAFACTORY_METAFACTORY_SIGNATURE, false); - } - this.contents[localContentsOffset++] = (byte) (indexForMetaFactory >> 8); - this.contents[localContentsOffset++] = (byte) indexForMetaFactory; - - // u2 num_bootstrap_arguments - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = (byte) 3; - - int functionalDescriptorIndex = this.constantPool.literalIndexForMethodType(functional.descriptor.original().signature()); - this.contents[localContentsOffset++] = (byte) (functionalDescriptorIndex >> 8); - this.contents[localContentsOffset++] = (byte) functionalDescriptorIndex; - - int methodHandleIndex = this.constantPool.literalIndexForMethodHandle(functional.binding.original()); // Speak of " implementation" (erased) version here, adaptations described below. - this.contents[localContentsOffset++] = (byte) (methodHandleIndex >> 8); - this.contents[localContentsOffset++] = (byte) methodHandleIndex; - - char [] instantiatedSignature = functional.descriptor.signature(); - int methodTypeIndex = this.constantPool.literalIndexForMethodType(instantiatedSignature); - this.contents[localContentsOffset++] = (byte) (methodTypeIndex >> 8); - this.contents[localContentsOffset++] = (byte) methodTypeIndex; - } - } - - int attributeLength = localContentsOffset - attributeLengthPosition - 4; - this.contents[attributeLengthPosition++] = (byte) (attributeLength >> 24); - this.contents[attributeLengthPosition++] = (byte) (attributeLength >> 16); - this.contents[attributeLengthPosition++] = (byte) (attributeLength >> 8); - this.contents[attributeLengthPosition++] = (byte) attributeLength; - this.contentsOffset = localContentsOffset; - return 1; - } - private int generateLineNumberAttribute() { - int localContentsOffset = this.contentsOffset; - int attributesNumber = 0; - /* Create and add the line number attribute (used for debugging) - * Build the pairs of: - * (bytecodePC lineNumber) - * according to the table of start line indexes and the pcToSourceMap table - * contained into the codestream - */ - int[] pcToSourceMapTable; - if (((pcToSourceMapTable = this.codeStream.pcToSourceMap) != null) - && (this.codeStream.pcToSourceMapSize != 0)) { - int lineNumberNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName); - if (localContentsOffset + 8 >= this.contents.length) { - resizeContents(8); - } - this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) lineNumberNameIndex; - int lineNumberTableOffset = localContentsOffset; - localContentsOffset += 6; - // leave space for attribute_length and line_number_table_length - int numberOfEntries = 0; - int length = this.codeStream.pcToSourceMapSize; - for (int i = 0; i < length;) { - // write the entry - if (localContentsOffset + 4 >= this.contents.length) { - resizeContents(4); - } - int pc = pcToSourceMapTable[i++]; - this.contents[localContentsOffset++] = (byte) (pc >> 8); - this.contents[localContentsOffset++] = (byte) pc; - int lineNumber = pcToSourceMapTable[i++]; - this.contents[localContentsOffset++] = (byte) (lineNumber >> 8); - this.contents[localContentsOffset++] = (byte) lineNumber; - numberOfEntries++; - } - // now we change the size of the line number attribute - int lineNumberAttr_length = numberOfEntries * 4 + 2; - this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 24); - this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 16); - this.contents[lineNumberTableOffset++] = (byte) (lineNumberAttr_length >> 8); - this.contents[lineNumberTableOffset++] = (byte) lineNumberAttr_length; - this.contents[lineNumberTableOffset++] = (byte) (numberOfEntries >> 8); - this.contents[lineNumberTableOffset++] = (byte) numberOfEntries; - attributesNumber = 1; - } - this.contentsOffset = localContentsOffset; - return attributesNumber; - } - // this is used for problem and synthetic methods - private int generateLineNumberAttribute(int problemLine) { - int localContentsOffset = this.contentsOffset; - if (localContentsOffset + 12 >= this.contents.length) { - resizeContents(12); - } - /* Create and add the line number attribute (used for debugging) - * Build the pairs of: - * (bytecodePC lineNumber) - * according to the table of start line indexes and the pcToSourceMap table - * contained into the codestream - */ - int lineNumberNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.LineNumberTableName); - this.contents[localContentsOffset++] = (byte) (lineNumberNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) lineNumberNameIndex; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 6; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 1; - // first entry at pc = 0 - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = (byte) (problemLine >> 8); - this.contents[localContentsOffset++] = (byte) problemLine; - // now we change the size of the line number attribute - this.contentsOffset = localContentsOffset; - return 1; - } - - private int generateLocalVariableTableAttribute(int code_length, boolean methodDeclarationIsStatic, boolean isSynthetic) { - int attributesNumber = 0; - int localContentsOffset = this.contentsOffset; - int numberOfEntries = 0; - int localVariableNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.LocalVariableTableName); - int maxOfEntries = 8 + 10 * (methodDeclarationIsStatic ? 0 : 1); - for (int i = 0; i < this.codeStream.allLocalsCounter; i++) { - LocalVariableBinding localVariableBinding = this.codeStream.locals[i]; - maxOfEntries += 10 * localVariableBinding.initializationCount; - } - // reserve enough space - if (localContentsOffset + maxOfEntries >= this.contents.length) { - resizeContents(maxOfEntries); - } - this.contents[localContentsOffset++] = (byte) (localVariableNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) localVariableNameIndex; - int localVariableTableOffset = localContentsOffset; - // leave space for attribute_length and local_variable_table_length - localContentsOffset += 6; - int nameIndex; - int descriptorIndex; - SourceTypeBinding declaringClassBinding = null; - if (!methodDeclarationIsStatic && !isSynthetic) { - numberOfEntries++; - this.contents[localContentsOffset++] = 0; // the startPC for this is always 0 - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = (byte) (code_length >> 8); - this.contents[localContentsOffset++] = (byte) code_length; - nameIndex = this.constantPool.literalIndex(ConstantPool.This); - this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); - this.contents[localContentsOffset++] = (byte) nameIndex; - declaringClassBinding = (SourceTypeBinding) - (this.codeStream.methodDeclaration != null ? this.codeStream.methodDeclaration.binding.declaringClass : this.codeStream.lambdaExpression.binding.declaringClass); - descriptorIndex = - this.constantPool.literalIndex( - declaringClassBinding.signature()); - this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8); - this.contents[localContentsOffset++] = (byte) descriptorIndex; - this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0 - this.contents[localContentsOffset++] = 0; - } - // used to remember the local variable with a generic type - int genericLocalVariablesCounter = 0; - LocalVariableBinding[] genericLocalVariables = null; - int numberOfGenericEntries = 0; - - for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) { - LocalVariableBinding localVariable = this.codeStream.locals[i]; - int initializationCount = localVariable.initializationCount; - if (initializationCount == 0) continue; - if (localVariable.declaration == null) continue; - final TypeBinding localVariableTypeBinding = localVariable.type; - boolean isParameterizedType = localVariableTypeBinding.isParameterizedType() || localVariableTypeBinding.isTypeVariable(); - if (isParameterizedType) { - if (genericLocalVariables == null) { - // we cannot have more than max locals - genericLocalVariables = new LocalVariableBinding[max]; - } - genericLocalVariables[genericLocalVariablesCounter++] = localVariable; - } - for (int j = 0; j < initializationCount; j++) { - int startPC = localVariable.initializationPCs[j << 1]; - int endPC = localVariable.initializationPCs[(j << 1) + 1]; - if (startPC != endPC) { // only entries for non zero length - if (endPC == -1) { - localVariable.declaringScope.problemReporter().abortDueToInternalError( - Messages.bind(Messages.abort_invalidAttribute, new String(localVariable.name)), - (ASTNode) localVariable.declaringScope.methodScope().referenceContext); - } - if (isParameterizedType) { - numberOfGenericEntries++; - } - // now we can safely add the local entry - numberOfEntries++; - this.contents[localContentsOffset++] = (byte) (startPC >> 8); - this.contents[localContentsOffset++] = (byte) startPC; - int length = endPC - startPC; - this.contents[localContentsOffset++] = (byte) (length >> 8); - this.contents[localContentsOffset++] = (byte) length; - nameIndex = this.constantPool.literalIndex(localVariable.name); - this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); - this.contents[localContentsOffset++] = (byte) nameIndex; - descriptorIndex = this.constantPool.literalIndex(localVariableTypeBinding.signature()); - this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8); - this.contents[localContentsOffset++] = (byte) descriptorIndex; - int resolvedPosition = localVariable.resolvedPosition; - this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8); - this.contents[localContentsOffset++] = (byte) resolvedPosition; - } - } - } - int value = numberOfEntries * 10 + 2; - this.contents[localVariableTableOffset++] = (byte) (value >> 24); - this.contents[localVariableTableOffset++] = (byte) (value >> 16); - this.contents[localVariableTableOffset++] = (byte) (value >> 8); - this.contents[localVariableTableOffset++] = (byte) value; - this.contents[localVariableTableOffset++] = (byte) (numberOfEntries >> 8); - this.contents[localVariableTableOffset] = (byte) numberOfEntries; - attributesNumber++; - - final boolean currentInstanceIsGeneric = - !methodDeclarationIsStatic - && declaringClassBinding != null - && declaringClassBinding.typeVariables != Binding.NO_TYPE_VARIABLES; - if (genericLocalVariablesCounter != 0 || currentInstanceIsGeneric) { - // add the local variable type table attribute - numberOfGenericEntries += (currentInstanceIsGeneric ? 1 : 0); - maxOfEntries = 8 + numberOfGenericEntries * 10; - // reserve enough space - if (localContentsOffset + maxOfEntries >= this.contents.length) { - resizeContents(maxOfEntries); - } - int localVariableTypeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.LocalVariableTypeTableName); - this.contents[localContentsOffset++] = (byte) (localVariableTypeNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) localVariableTypeNameIndex; - value = numberOfGenericEntries * 10 + 2; - this.contents[localContentsOffset++] = (byte) (value >> 24); - this.contents[localContentsOffset++] = (byte) (value >> 16); - this.contents[localContentsOffset++] = (byte) (value >> 8); - this.contents[localContentsOffset++] = (byte) value; - this.contents[localContentsOffset++] = (byte) (numberOfGenericEntries >> 8); - this.contents[localContentsOffset++] = (byte) numberOfGenericEntries; - if (currentInstanceIsGeneric) { - this.contents[localContentsOffset++] = 0; // the startPC for this is always 0 - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = (byte) (code_length >> 8); - this.contents[localContentsOffset++] = (byte) code_length; - nameIndex = this.constantPool.literalIndex(ConstantPool.This); - this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); - this.contents[localContentsOffset++] = (byte) nameIndex; - descriptorIndex = this.constantPool.literalIndex(declaringClassBinding.genericTypeSignature()); - this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8); - this.contents[localContentsOffset++] = (byte) descriptorIndex; - this.contents[localContentsOffset++] = 0;// the resolved position for this is always 0 - this.contents[localContentsOffset++] = 0; - } - - for (int i = 0; i < genericLocalVariablesCounter; i++) { - LocalVariableBinding localVariable = genericLocalVariables[i]; - for (int j = 0; j < localVariable.initializationCount; j++) { - int startPC = localVariable.initializationPCs[j << 1]; - int endPC = localVariable.initializationPCs[(j << 1) + 1]; - if (startPC != endPC) { - // only entries for non zero length - // now we can safely add the local entry - this.contents[localContentsOffset++] = (byte) (startPC >> 8); - this.contents[localContentsOffset++] = (byte) startPC; - int length = endPC - startPC; - this.contents[localContentsOffset++] = (byte) (length >> 8); - this.contents[localContentsOffset++] = (byte) length; - nameIndex = this.constantPool.literalIndex(localVariable.name); - this.contents[localContentsOffset++] = (byte) (nameIndex >> 8); - this.contents[localContentsOffset++] = (byte) nameIndex; - descriptorIndex = this.constantPool.literalIndex(localVariable.type.genericTypeSignature()); - this.contents[localContentsOffset++] = (byte) (descriptorIndex >> 8); - this.contents[localContentsOffset++] = (byte) descriptorIndex; - int resolvedPosition = localVariable.resolvedPosition; - this.contents[localContentsOffset++] = (byte) (resolvedPosition >> 8); - this.contents[localContentsOffset++] = (byte) resolvedPosition; - } - } - } - attributesNumber++; - } - this.contentsOffset = localContentsOffset; - return attributesNumber; - } - /** - * INTERNAL USE-ONLY - * That method generates the attributes of a code attribute. - * They could be: - * - an exception attribute for each try/catch found inside the method - * - a deprecated attribute - * - a synthetic attribute for synthetic access methods - * - * It returns the number of attributes created for the code attribute. - * - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding - * @return <CODE>int</CODE> - */ - public int generateMethodInfoAttributes(MethodBinding methodBinding, List extraAttributes) { // AspectJ: extra parameter - // leave two bytes for the attribute_number - this.contentsOffset += 2; - if (this.contentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - // now we can handle all the attribute for that method info: - // it could be: - // - a CodeAttribute - // - a ExceptionAttribute - // - a DeprecatedAttribute - // - a SyntheticAttribute - - // Exception attribute - ReferenceBinding[] thrownsExceptions; - int attributesNumber = 0; - if ((thrownsExceptions = methodBinding.thrownExceptions) != Binding.NO_EXCEPTIONS) { - // The method has a throw clause. So we need to add an exception attribute - // check that there is enough space to write all the bytes for the exception attribute - attributesNumber += generateExceptionsAttribute(thrownsExceptions); - } - if (methodBinding.isDeprecated()) { - // Deprecated attribute - attributesNumber += generateDeprecatedAttribute(); - } - if (this.targetJDK < ClassFileConstants.JDK1_5) { - if (methodBinding.isSynthetic()) { - attributesNumber += generateSyntheticAttribute(); - } - if (methodBinding.isVarargs()) { - attributesNumber += generateVarargsAttribute(); - } - } - // add signature attribute - char[] genericSignature = methodBinding.genericSignature(); - if (genericSignature != null) { - attributesNumber += generateSignatureAttribute(genericSignature); - } - if (this.targetJDK >= ClassFileConstants.JDK1_4) { - AbstractMethodDeclaration methodDeclaration = methodBinding.sourceMethod(); - if (methodBinding instanceof SyntheticMethodBinding) { - SyntheticMethodBinding syntheticMethod = (SyntheticMethodBinding) methodBinding; - if (syntheticMethod.purpose == SyntheticMethodBinding.SuperMethodAccess && CharOperation.equals(syntheticMethod.selector, syntheticMethod.targetMethod.selector)) - methodDeclaration = ((SyntheticMethodBinding)methodBinding).targetMethod.sourceMethod(); - } - if (methodDeclaration != null) { - Annotation[] annotations = methodDeclaration.annotations; - if (annotations != null) { - attributesNumber += generateRuntimeAnnotations(annotations, methodBinding.isConstructor() ? TagBits.AnnotationForConstructor : TagBits.AnnotationForMethod); - } - if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) { - Argument[] arguments = methodDeclaration.arguments; - if (arguments != null) { - attributesNumber += generateRuntimeAnnotationsForParameters(arguments); - } - } - } else { - LambdaExpression lambda = methodBinding.sourceLambda(); - if (lambda != null) { - if ((methodBinding.tagBits & TagBits.HasParameterAnnotations) != 0) { - Argument[] arguments = lambda.arguments(); - if (arguments != null) { - int parameterCount = methodBinding.parameters.length; - int argumentCount = arguments.length; - if (parameterCount > argumentCount) { // synthetics prefixed - int redShift = parameterCount - argumentCount; - System.arraycopy(arguments, 0, arguments = new Argument[parameterCount], redShift, argumentCount); - for (int i = 0; i < redShift; i++) - arguments[i] = new Argument(CharOperation.NO_CHAR, 0, null, 0); - } - attributesNumber += generateRuntimeAnnotationsForParameters(arguments); - } - } - } - } - } - if ((methodBinding.tagBits & TagBits.HasMissingType) != 0) { - this.missingTypes = methodBinding.collectMissingTypes(this.missingTypes); - } - // AspectJ Extension - if (extraAttributes != null) { - for (int i=0, len = extraAttributes.size(); i < len; i++) { - IAttribute attribute = (IAttribute)extraAttributes.get(i); - short nameIndex = (short)constantPool.literalIndex(attribute.getNameChars()); - writeToContents(attribute.getAllBytes(nameIndex,constantPool)); - attributesNumber++; - } - } - // End AspectJ Extension - return attributesNumber; - } - // AspectJ Extension - new method stub that can pass 3rd param - public int generateMethodInfoAttributes(MethodBinding methodBinding) { - return generateMethodInfoAttributes(methodBinding,(List)null); - } - // End AspectJ Extension - public int generateMethodInfoAttributes(MethodBinding methodBinding, AnnotationMethodDeclaration declaration) { - int attributesNumber = generateMethodInfoAttributes(methodBinding); - int attributeOffset = this.contentsOffset; - if ((declaration.modifiers & ClassFileConstants.AccAnnotationDefault) != 0) { - // add an annotation default attribute - attributesNumber += generateAnnotationDefaultAttribute(declaration, attributeOffset); - } - return attributesNumber; - } - /** - * INTERNAL USE-ONLY - * That method generates the header of a method info: - * The header consists in: - * - the access flags - * - the name index of the method name inside the constant pool - * - the descriptor index of the signature of the method inside the constant pool. - * - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding - */ - public void generateMethodInfoHeader(MethodBinding methodBinding) { - generateMethodInfoHeader(methodBinding, methodBinding.modifiers); - } - - /** - * INTERNAL USE-ONLY - * That method generates the header of a method info: - * The header consists in: - * - the access flags - * - the name index of the method name inside the constant pool - * - the descriptor index of the signature of the method inside the constant pool. - * - * @param methodBinding org.aspectj.org.eclipse.jdt.internal.compiler.lookup.MethodBinding - * @param accessFlags the access flags - */ - public void generateMethodInfoHeader(MethodBinding methodBinding, int accessFlags) { - // check that there is enough space to write all the bytes for the method info corresponding - // to the @methodBinding - this.methodCount++; // add one more method - if (this.contentsOffset + 10 >= this.contents.length) { - resizeContents(10); - } - if (this.targetJDK < ClassFileConstants.JDK1_5) { - // pre 1.5, synthetic is an attribute, not a modifier - // pre 1.5, varargs is an attribute, not a modifier (-target jsr14 mode) - accessFlags &= ~(ClassFileConstants.AccSynthetic | ClassFileConstants.AccVarargs); - } - if ((methodBinding.tagBits & TagBits.ClearPrivateModifier) != 0) { - accessFlags &= ~ClassFileConstants.AccPrivate; - } - this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8); - this.contents[this.contentsOffset++] = (byte) accessFlags; - int nameIndex = this.constantPool.literalIndex(methodBinding.selector); - this.contents[this.contentsOffset++] = (byte) (nameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) nameIndex; - int descriptorIndex = this.constantPool.literalIndex(methodBinding.signature(this)); - this.contents[this.contentsOffset++] = (byte) (descriptorIndex >> 8); - this.contents[this.contentsOffset++] = (byte) descriptorIndex; - } - - public void addSyntheticDeserializeLambda(SyntheticMethodBinding methodBinding, SyntheticMethodBinding[] syntheticMethodBindings ) { - generateMethodInfoHeader(methodBinding); - int methodAttributeOffset = this.contentsOffset; - // this will add exception attribute, synthetic attribute, deprecated attribute,... - int attributeNumber = generateMethodInfoAttributes(methodBinding); - // Code attribute - int codeAttributeOffset = this.contentsOffset; - attributeNumber++; // add code attribute - generateCodeAttributeHeader(); - this.codeStream.init(this); - this.codeStream.generateSyntheticBodyForDeserializeLambda(methodBinding, syntheticMethodBindings); - completeCodeAttributeForSyntheticMethod( - methodBinding, - codeAttributeOffset, - ((SourceTypeBinding) methodBinding.declaringClass) - .scope - .referenceCompilationUnit() - .compilationResult - .getLineSeparatorPositions()); - // update the number of attributes - if ((this.produceAttributes & ClassFileConstants.ATTR_METHOD_PARAMETERS) != 0) { - attributeNumber += generateMethodParameters(methodBinding); - } - this.contents[methodAttributeOffset++] = (byte) (attributeNumber >> 8); - this.contents[methodAttributeOffset] = (byte) attributeNumber; - } - - /** - * INTERNAL USE-ONLY - * That method generates the method info header of a clinit: - * The header consists in: - * - the access flags (always default access + static) - * - the name index of the method name (always <clinit>) inside the constant pool - * - the descriptor index of the signature (always ()V) of the method inside the constant pool. - */ - public void generateMethodInfoHeaderForClinit() { - // check that there is enough space to write all the bytes for the method info corresponding - // to the @methodBinding - this.methodCount++; // add one more method - if (this.contentsOffset + 10 >= this.contents.length) { - resizeContents(10); - } - this.contents[this.contentsOffset++] = (byte) ((ClassFileConstants.AccDefault | ClassFileConstants.AccStatic) >> 8); - this.contents[this.contentsOffset++] = (byte) (ClassFileConstants.AccDefault | ClassFileConstants.AccStatic); - int nameIndex = this.constantPool.literalIndex(ConstantPool.Clinit); - this.contents[this.contentsOffset++] = (byte) (nameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) nameIndex; - int descriptorIndex = - this.constantPool.literalIndex(ConstantPool.ClinitSignature); - this.contents[this.contentsOffset++] = (byte) (descriptorIndex >> 8); - this.contents[this.contentsOffset++] = (byte) descriptorIndex; - // We know that we won't get more than 1 attribute: the code attribute - this.contents[this.contentsOffset++] = 0; - this.contents[this.contentsOffset++] = 1; - } - - /** - * INTERNAL USE-ONLY - * Generate the byte for problem method infos that correspond to missing abstract methods. - * http://dev.eclipse.org/bugs/show_bug.cgi?id=3179 - * - * @param methodDeclarations Array of all missing abstract methods - */ - public void generateMissingAbstractMethods(MethodDeclaration[] methodDeclarations, CompilationResult compilationResult) { - if (methodDeclarations != null) { - TypeDeclaration currentDeclaration = this.referenceBinding.scope.referenceContext; - int typeDeclarationSourceStart = currentDeclaration.sourceStart(); - int typeDeclarationSourceEnd = currentDeclaration.sourceEnd(); - for (int i = 0, max = methodDeclarations.length; i < max; i++) { - MethodDeclaration methodDeclaration = methodDeclarations[i]; - MethodBinding methodBinding = methodDeclaration.binding; - String readableName = new String(methodBinding.readableName()); - CategorizedProblem[] problems = compilationResult.problems; - int problemsCount = compilationResult.problemCount; - for (int j = 0; j < problemsCount; j++) { - CategorizedProblem problem = problems[j]; - if (problem != null - && problem.getID() == IProblem.AbstractMethodMustBeImplemented - && problem.getMessage().indexOf(readableName) != -1 - && problem.getSourceStart() >= typeDeclarationSourceStart - && problem.getSourceEnd() <= typeDeclarationSourceEnd) { - // we found a match - addMissingAbstractProblemMethod(methodDeclaration, methodBinding, problem, compilationResult); - } - } - } - } - } - - private void generateMissingTypesAttribute() { - int initialSize = this.missingTypes.size(); - int[] missingTypesIndexes = new int[initialSize]; - int numberOfMissingTypes = 0; - if (initialSize > 1) { - Collections.sort(this.missingTypes, new Comparator() { - public int compare(Object o1, Object o2) { - TypeBinding typeBinding1 = (TypeBinding) o1; - TypeBinding typeBinding2 = (TypeBinding) o2; - return CharOperation.compareTo(typeBinding1.constantPoolName(), typeBinding2.constantPoolName()); - } - }); - } - int previousIndex = 0; - next: for (int i = 0; i < initialSize; i++) { - int missingTypeIndex = this.constantPool.literalIndexForType((TypeBinding) this.missingTypes.get(i)); - if (previousIndex == missingTypeIndex) { - continue next; - } - previousIndex = missingTypeIndex; - missingTypesIndexes[numberOfMissingTypes++] = missingTypeIndex; - } - // we don't need to resize as we interate from 0 to numberOfMissingTypes when recording the indexes in the .class file - int attributeLength = numberOfMissingTypes * 2 + 2; - if (this.contentsOffset + attributeLength + 6 >= this.contents.length) { - resizeContents(attributeLength + 6); - } - int missingTypesNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.MissingTypesName); - this.contents[this.contentsOffset++] = (byte) (missingTypesNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) missingTypesNameIndex; - - // generate attribute length - this.contents[this.contentsOffset++] = (byte) (attributeLength >> 24); - this.contents[this.contentsOffset++] = (byte) (attributeLength >> 16); - this.contents[this.contentsOffset++] = (byte) (attributeLength >> 8); - this.contents[this.contentsOffset++] = (byte) attributeLength; - - // generate number of missing types - this.contents[this.contentsOffset++] = (byte) (numberOfMissingTypes >> 8); - this.contents[this.contentsOffset++] = (byte) numberOfMissingTypes; - // generate entry for each missing type - for (int i = 0; i < numberOfMissingTypes; i++) { - int missingTypeIndex = missingTypesIndexes[i]; - this.contents[this.contentsOffset++] = (byte) (missingTypeIndex >> 8); - this.contents[this.contentsOffset++] = (byte) missingTypeIndex; - } - } - - /** - * @param annotations - * @param targetMask allowed targets - * @return the number of attributes created while dumping the annotations in the .class file - */ - private int generateRuntimeAnnotations(final Annotation[] annotations, final long targetMask) { - int attributesNumber = 0; - final int length = annotations.length; - int visibleAnnotationsCounter = 0; - int invisibleAnnotationsCounter = 0; - for (int i = 0; i < length; i++) { - Annotation annotation; - if ((annotation = annotations[i].getPersistibleAnnotation()) == null) continue; // already packaged into container. - long annotationMask = annotation.resolvedType != null ? annotation.resolvedType.getAnnotationTagBits() & TagBits.AnnotationTargetMASK : 0; - // AspectJ Extension: this prevents a Type targeting annotation being stashed on a - // method representing an 'declare @type'. So don't enforce this restriction -// if (annotationMask != 0 && (annotationMask & targetMask) == 0) continue; - // AspectJ Extension: End - if (annotation.isRuntimeInvisible() || annotation.isRuntimeTypeInvisible()) { - invisibleAnnotationsCounter++; - } else if (annotation.isRuntimeVisible() || annotation.isRuntimeTypeVisible()) { - visibleAnnotationsCounter++; - } - } - - int annotationAttributeOffset = this.contentsOffset; - int constantPOffset = this.constantPool.currentOffset; - int constantPoolIndex = this.constantPool.currentIndex; - if (invisibleAnnotationsCounter != 0) { - if (this.contentsOffset + 10 >= this.contents.length) { - resizeContents(10); - } - int runtimeInvisibleAnnotationsAttributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleAnnotationsName); - this.contents[this.contentsOffset++] = (byte) (runtimeInvisibleAnnotationsAttributeNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) runtimeInvisibleAnnotationsAttributeNameIndex; - int attributeLengthOffset = this.contentsOffset; - this.contentsOffset += 4; // leave space for the attribute length - - int annotationsLengthOffset = this.contentsOffset; - this.contentsOffset += 2; // leave space for the annotations length - - int counter = 0; - loop: for (int i = 0; i < length; i++) { - if (invisibleAnnotationsCounter == 0) break loop; - Annotation annotation; - if ((annotation = annotations[i].getPersistibleAnnotation()) == null) continue; // already packaged into container. - long annotationMask = annotation.resolvedType != null ? annotation.resolvedType.getAnnotationTagBits() & TagBits.AnnotationTargetMASK : 0; - // AspectJ Extension: this prevents a Type targeting annotation being stashed on a - // method representing an 'declare @type'. So don't enforce this restriction -// if (annotationMask != 0 && (annotationMask & targetMask) == 0) continue; - // AspectJ Extension: end - if (annotation.isRuntimeInvisible() || annotation.isRuntimeTypeInvisible()) { - int currentAnnotationOffset = this.contentsOffset; - generateAnnotation(annotation, currentAnnotationOffset); - invisibleAnnotationsCounter--; - if (this.contentsOffset != currentAnnotationOffset) { - counter++; - } - } - } - if (counter != 0) { - this.contents[annotationsLengthOffset++] = (byte) (counter >> 8); - this.contents[annotationsLengthOffset++] = (byte) counter; - - int attributeLength = this.contentsOffset - attributeLengthOffset - 4; - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8); - this.contents[attributeLengthOffset++] = (byte) attributeLength; - attributesNumber++; - } else { - this.contentsOffset = annotationAttributeOffset; - // reset the constant pool to its state before the clinit - this.constantPool.resetForAttributeName(AttributeNamesConstants.RuntimeInvisibleAnnotationsName, constantPoolIndex, constantPOffset); - } - } - - annotationAttributeOffset = this.contentsOffset; - constantPOffset = this.constantPool.currentOffset; - constantPoolIndex = this.constantPool.currentIndex; - if (visibleAnnotationsCounter != 0) { - if (this.contentsOffset + 10 >= this.contents.length) { - resizeContents(10); - } - int runtimeVisibleAnnotationsAttributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleAnnotationsName); - this.contents[this.contentsOffset++] = (byte) (runtimeVisibleAnnotationsAttributeNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) runtimeVisibleAnnotationsAttributeNameIndex; - int attributeLengthOffset = this.contentsOffset; - this.contentsOffset += 4; // leave space for the attribute length - - int annotationsLengthOffset = this.contentsOffset; - this.contentsOffset += 2; // leave space for the annotations length - - int counter = 0; - loop: for (int i = 0; i < length; i++) { - if (visibleAnnotationsCounter == 0) break loop; - Annotation annotation; - if ((annotation = annotations[i].getPersistibleAnnotation()) == null) continue; // already packaged into container. - long annotationMask = annotation.resolvedType != null ? annotation.resolvedType.getAnnotationTagBits() & TagBits.AnnotationTargetMASK : 0; - // AspectJ Extension: this prevents a Type targeting annotation being stashed on a - // method representing an 'declare @type'. So don't enforce this restriction -// if (annotationMask != 0 && (annotationMask & targetMask) == 0) continue; - // AspectJ Extension: end - if (annotation.isRuntimeVisible() || annotation.isRuntimeTypeVisible()) { - visibleAnnotationsCounter--; - int currentAnnotationOffset = this.contentsOffset; - generateAnnotation(annotation, currentAnnotationOffset); - if (this.contentsOffset != currentAnnotationOffset) { - counter++; - } - } - } - if (counter != 0) { - this.contents[annotationsLengthOffset++] = (byte) (counter >> 8); - this.contents[annotationsLengthOffset++] = (byte) counter; - - int attributeLength = this.contentsOffset - attributeLengthOffset - 4; - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8); - this.contents[attributeLengthOffset++] = (byte) attributeLength; - attributesNumber++; - } else { - this.contentsOffset = annotationAttributeOffset; - this.constantPool.resetForAttributeName(AttributeNamesConstants.RuntimeVisibleAnnotationsName, constantPoolIndex, constantPOffset); - } - } - return attributesNumber; - } - - private int generateRuntimeAnnotationsForParameters(Argument[] arguments) { - final int argumentsLength = arguments.length; - final int VISIBLE_INDEX = 0; - final int INVISIBLE_INDEX = 1; - int invisibleParametersAnnotationsCounter = 0; - int visibleParametersAnnotationsCounter = 0; - int[][] annotationsCounters = new int[argumentsLength][2]; - for (int i = 0; i < argumentsLength; i++) { - Argument argument = arguments[i]; - Annotation[] annotations = argument.annotations; - if (annotations != null) { - for (int j = 0, max2 = annotations.length; j < max2; j++) { - Annotation annotation; - if ((annotation = annotations[j].getPersistibleAnnotation()) == null) continue; // already packaged into container. - long annotationMask = annotation.resolvedType != null ? annotation.resolvedType.getAnnotationTagBits() & TagBits.AnnotationTargetMASK : 0; - if (annotationMask != 0 && (annotationMask & TagBits.AnnotationForParameter) == 0) continue; - if (annotation.isRuntimeInvisible()) { - annotationsCounters[i][INVISIBLE_INDEX]++; - invisibleParametersAnnotationsCounter++; - } else if (annotation.isRuntimeVisible()) { - annotationsCounters[i][VISIBLE_INDEX]++; - visibleParametersAnnotationsCounter++; - } - } - } - } - int attributesNumber = 0; - int annotationAttributeOffset = this.contentsOffset; - if (invisibleParametersAnnotationsCounter != 0) { - int globalCounter = 0; - if (this.contentsOffset + 7 >= this.contents.length) { - resizeContents(7); - } - int attributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleParameterAnnotationsName); - this.contents[this.contentsOffset++] = (byte) (attributeNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) attributeNameIndex; - int attributeLengthOffset = this.contentsOffset; - this.contentsOffset += 4; // leave space for the attribute length - - this.contents[this.contentsOffset++] = (byte) argumentsLength; - for (int i = 0; i < argumentsLength; i++) { - if (this.contentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - if (invisibleParametersAnnotationsCounter == 0) { - this.contents[this.contentsOffset++] = (byte) 0; - this.contents[this.contentsOffset++] = (byte) 0; - } else { - final int numberOfInvisibleAnnotations = annotationsCounters[i][INVISIBLE_INDEX]; - int invisibleAnnotationsOffset = this.contentsOffset; - // leave space for number of annotations - this.contentsOffset += 2; - int counter = 0; - if (numberOfInvisibleAnnotations != 0) { - Argument argument = arguments[i]; - Annotation[] annotations = argument.annotations; - for (int j = 0, max = annotations.length; j < max; j++) { - Annotation annotation; - if ((annotation = annotations[j].getPersistibleAnnotation()) == null) continue; // already packaged into container. - long annotationMask = annotation.resolvedType != null ? annotation.resolvedType.getAnnotationTagBits() & TagBits.AnnotationTargetMASK : 0; - if (annotationMask != 0 && (annotationMask & TagBits.AnnotationForParameter) == 0) continue; - if (annotation.isRuntimeInvisible()) { - int currentAnnotationOffset = this.contentsOffset; - generateAnnotation(annotation, currentAnnotationOffset); - if (this.contentsOffset != currentAnnotationOffset) { - counter++; - globalCounter++; - } - invisibleParametersAnnotationsCounter--; - } - } - } - this.contents[invisibleAnnotationsOffset++] = (byte) (counter >> 8); - this.contents[invisibleAnnotationsOffset] = (byte) counter; - } - } - if (globalCounter != 0) { - int attributeLength = this.contentsOffset - attributeLengthOffset - 4; - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8); - this.contents[attributeLengthOffset++] = (byte) attributeLength; - attributesNumber++; - } else { - // if globalCounter is 0, this means that the code generation for all visible annotations failed - this.contentsOffset = annotationAttributeOffset; - } - } - if (visibleParametersAnnotationsCounter != 0) { - int globalCounter = 0; - if (this.contentsOffset + 7 >= this.contents.length) { - resizeContents(7); - } - int attributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleParameterAnnotationsName); - this.contents[this.contentsOffset++] = (byte) (attributeNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) attributeNameIndex; - int attributeLengthOffset = this.contentsOffset; - this.contentsOffset += 4; // leave space for the attribute length - - this.contents[this.contentsOffset++] = (byte) argumentsLength; - for (int i = 0; i < argumentsLength; i++) { - if (this.contentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - if (visibleParametersAnnotationsCounter == 0) { - this.contents[this.contentsOffset++] = (byte) 0; - this.contents[this.contentsOffset++] = (byte) 0; - } else { - final int numberOfVisibleAnnotations = annotationsCounters[i][VISIBLE_INDEX]; - int visibleAnnotationsOffset = this.contentsOffset; - // leave space for number of annotations - this.contentsOffset += 2; - int counter = 0; - if (numberOfVisibleAnnotations != 0) { - Argument argument = arguments[i]; - Annotation[] annotations = argument.annotations; - for (int j = 0, max = annotations.length; j < max; j++) { - Annotation annotation; - if ((annotation = annotations[j].getPersistibleAnnotation()) == null) continue; // already packaged into container. - long annotationMask = annotation.resolvedType != null ? annotation.resolvedType.getAnnotationTagBits() & TagBits.AnnotationTargetMASK : 0; - if (annotationMask != 0 && (annotationMask & TagBits.AnnotationForParameter) == 0) continue; - if (annotation.isRuntimeVisible()) { - int currentAnnotationOffset = this.contentsOffset; - generateAnnotation(annotation, currentAnnotationOffset); - if (this.contentsOffset != currentAnnotationOffset) { - counter++; - globalCounter++; - } - visibleParametersAnnotationsCounter--; - } - } - } - this.contents[visibleAnnotationsOffset++] = (byte) (counter >> 8); - this.contents[visibleAnnotationsOffset] = (byte) counter; - } - } - if (globalCounter != 0) { - int attributeLength = this.contentsOffset - attributeLengthOffset - 4; - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8); - this.contents[attributeLengthOffset++] = (byte) attributeLength; - attributesNumber++; - } else { - // if globalCounter is 0, this means that the code generation for all visible annotations failed - this.contentsOffset = annotationAttributeOffset; - } - } - return attributesNumber; - } - - /** - * @param annotationContexts the given annotation contexts - * @param visibleTypeAnnotationsNumber the given number of visible type annotations - * @param invisibleTypeAnnotationsNumber the given number of invisible type annotations - * @return the number of attributes created while dumping the annotations in the .class file - */ - private int generateRuntimeTypeAnnotations( - final AnnotationContext[] annotationContexts, - int visibleTypeAnnotationsNumber, - int invisibleTypeAnnotationsNumber) { - int attributesNumber = 0; - final int length = annotationContexts.length; - - int visibleTypeAnnotationsCounter = visibleTypeAnnotationsNumber; - int invisibleTypeAnnotationsCounter = invisibleTypeAnnotationsNumber; - int annotationAttributeOffset = this.contentsOffset; - int constantPOffset = this.constantPool.currentOffset; - int constantPoolIndex = this.constantPool.currentIndex; - if (invisibleTypeAnnotationsCounter != 0) { - if (this.contentsOffset + 10 >= this.contents.length) { - resizeContents(10); - } - int runtimeInvisibleAnnotationsAttributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.RuntimeInvisibleTypeAnnotationsName); - this.contents[this.contentsOffset++] = (byte) (runtimeInvisibleAnnotationsAttributeNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) runtimeInvisibleAnnotationsAttributeNameIndex; - int attributeLengthOffset = this.contentsOffset; - this.contentsOffset += 4; // leave space for the attribute length - - int annotationsLengthOffset = this.contentsOffset; - this.contentsOffset += 2; // leave space for the annotations length - - int counter = 0; - loop: for (int i = 0; i < length; i++) { - if (invisibleTypeAnnotationsCounter == 0) break loop; - AnnotationContext annotationContext = annotationContexts[i]; - if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) { - int currentAnnotationOffset = this.contentsOffset; - generateTypeAnnotation(annotationContext, currentAnnotationOffset); - invisibleTypeAnnotationsCounter--; - if (this.contentsOffset != currentAnnotationOffset) { - counter++; - } - } - } - if (counter != 0) { - this.contents[annotationsLengthOffset++] = (byte) (counter >> 8); - this.contents[annotationsLengthOffset++] = (byte) counter; - - int attributeLength = this.contentsOffset - attributeLengthOffset - 4; - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8); - this.contents[attributeLengthOffset++] = (byte) attributeLength; - attributesNumber++; - } else { - this.contentsOffset = annotationAttributeOffset; - // reset the constant pool to its state before the clinit - this.constantPool.resetForAttributeName(AttributeNamesConstants.RuntimeInvisibleTypeAnnotationsName, constantPoolIndex, constantPOffset); - } - } - - annotationAttributeOffset = this.contentsOffset; - constantPOffset = this.constantPool.currentOffset; - constantPoolIndex = this.constantPool.currentIndex; - if (visibleTypeAnnotationsCounter != 0) { - if (this.contentsOffset + 10 >= this.contents.length) { - resizeContents(10); - } - int runtimeVisibleAnnotationsAttributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.RuntimeVisibleTypeAnnotationsName); - this.contents[this.contentsOffset++] = (byte) (runtimeVisibleAnnotationsAttributeNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) runtimeVisibleAnnotationsAttributeNameIndex; - int attributeLengthOffset = this.contentsOffset; - this.contentsOffset += 4; // leave space for the attribute length - - int annotationsLengthOffset = this.contentsOffset; - this.contentsOffset += 2; // leave space for the annotations length - - int counter = 0; - loop: for (int i = 0; i < length; i++) { - if (visibleTypeAnnotationsCounter == 0) break loop; - AnnotationContext annotationContext = annotationContexts[i]; - if ((annotationContext.visibility & AnnotationContext.VISIBLE) != 0) { - visibleTypeAnnotationsCounter--; - int currentAnnotationOffset = this.contentsOffset; - generateTypeAnnotation(annotationContext, currentAnnotationOffset); - if (this.contentsOffset != currentAnnotationOffset) { - counter++; - } - } - } - if (counter != 0) { - this.contents[annotationsLengthOffset++] = (byte) (counter >> 8); - this.contents[annotationsLengthOffset++] = (byte) counter; - - int attributeLength = this.contentsOffset - attributeLengthOffset - 4; - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 24); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 16); - this.contents[attributeLengthOffset++] = (byte) (attributeLength >> 8); - this.contents[attributeLengthOffset++] = (byte) attributeLength; - attributesNumber++; - } else { - this.contentsOffset = annotationAttributeOffset; - this.constantPool.resetForAttributeName(AttributeNamesConstants.RuntimeVisibleTypeAnnotationsName, constantPoolIndex, constantPOffset); - } - } - return attributesNumber; - } - - /** - * @param binding the given method binding - * @return the number of attributes created while dumping he method's parameters in the .class file (0 or 1) - */ - private int generateMethodParameters(final MethodBinding binding) { - - int initialContentsOffset = this.contentsOffset; - int length = 0; // count of actual parameters - - AbstractMethodDeclaration methodDeclaration = binding.sourceMethod(); - - boolean isConstructor = binding.isConstructor(); - TypeBinding[] targetParameters = binding.parameters; - ReferenceBinding declaringClass = binding.declaringClass; - - if (declaringClass.isEnum()) { - if (isConstructor) { // insert String name,int ordinal - length = writeArgumentName(ConstantPool.EnumName, ClassFileConstants.AccSynthetic, length); - length = writeArgumentName(ConstantPool.EnumOrdinal, ClassFileConstants.AccSynthetic, length); - } else if (CharOperation.equals(ConstantPool.ValueOf, binding.selector)) { // insert String name - length = writeArgumentName(ConstantPool.Name, ClassFileConstants.AccMandated, length); - targetParameters = Binding.NO_PARAMETERS; // Override "unknown" synthetics below - } - } - - boolean needSynthetics = isConstructor && declaringClass.isNestedType(); - if (needSynthetics) { - // Take into account the synthetic argument names - // This tracks JLS8, paragraph 8.8.9 - boolean anonymousWithLocalSuper = declaringClass.isAnonymousType() && declaringClass.superclass().isLocalType(); - boolean anonymousWithNestedSuper = declaringClass.isAnonymousType() && declaringClass.superclass().isNestedType(); - boolean isImplicitlyDeclared = ((! declaringClass.isPrivate()) || declaringClass.isAnonymousType()) && !anonymousWithLocalSuper; - ReferenceBinding[] syntheticArgumentTypes = declaringClass.syntheticEnclosingInstanceTypes(); - if (syntheticArgumentTypes != null) { - for (int i = 0, count = syntheticArgumentTypes.length; i < count; i++) { - // This behaviour tracks JLS 15.9.5.1 - // This covers that the parameter ending up in a nested class must be mandated "on the way in", even if it - // isn't the first. The practical relevance of this is questionable, since the constructor call will be - // generated by the same constructor. - boolean couldForwardToMandated = anonymousWithNestedSuper ? declaringClass.superclass().enclosingType().equals(syntheticArgumentTypes[i]) : true; - int modifier = couldForwardToMandated && isImplicitlyDeclared ? ClassFileConstants.AccMandated : ClassFileConstants.AccSynthetic; - char[] name = CharOperation.concat( - TypeConstants.SYNTHETIC_ENCLOSING_INSTANCE_PREFIX, - String.valueOf(i).toCharArray()); // cannot use depth, can be identical - length = writeArgumentName(name, modifier | ClassFileConstants.AccFinal, length); - } - } - if (binding instanceof SyntheticMethodBinding) { - targetParameters = ((SyntheticMethodBinding)binding).targetMethod.parameters; - methodDeclaration = ((SyntheticMethodBinding)binding).targetMethod.sourceMethod(); - } - } - if (targetParameters != Binding.NO_PARAMETERS) { - Argument[] arguments = null; - if (methodDeclaration != null && methodDeclaration.arguments != null) { - arguments = methodDeclaration.arguments; - } else if (binding.sourceLambda() != null) { // SyntheticMethodBinding, purpose : LambdaMethod. - arguments = binding.sourceLambda().arguments; - } - for (int i = 0, max = targetParameters.length, argumentsLength = arguments != null ? arguments.length : 0; i < max; i++) { - if (argumentsLength > i && arguments[i] != null) { - Argument argument = arguments[i]; - length = writeArgumentName(argument.name, argument.binding.modifiers, length); - } else { - length = writeArgumentName(null, ClassFileConstants.AccSynthetic, length); - } - } - } - if (needSynthetics) { - SyntheticArgumentBinding[] syntheticOuterArguments = declaringClass.syntheticOuterLocalVariables(); - int count = syntheticOuterArguments == null ? 0 : syntheticOuterArguments.length; - for (int i = 0; i < count; i++) { - length = writeArgumentName(syntheticOuterArguments[i].name, syntheticOuterArguments[i].modifiers | ClassFileConstants.AccSynthetic, length); - } - // move the extra padding arguments of the synthetic constructor invocation to the end - for (int i = targetParameters.length, extraLength = binding.parameters.length; i < extraLength; i++) { - TypeBinding parameter = binding.parameters[i]; - length = writeArgumentName(parameter.constantPoolName(), ClassFileConstants.AccSynthetic, length); - } - } - - if (length > 0) { - // so we actually output the parameter - int attributeLength = 1 + 4 * length; // u1 for count, u2+u2 per parameter - if (this.contentsOffset + 6 + attributeLength >= this.contents.length) { - resizeContents(6 + attributeLength); - } - int methodParametersNameIndex = this.constantPool.literalIndex(AttributeNamesConstants.MethodParametersName); - this.contents[initialContentsOffset++] = (byte) (methodParametersNameIndex >> 8); - this.contents[initialContentsOffset++] = (byte) methodParametersNameIndex; - this.contents[initialContentsOffset++] = (byte) (attributeLength >> 24); - this.contents[initialContentsOffset++] = (byte) (attributeLength >> 16); - this.contents[initialContentsOffset++] = (byte) (attributeLength >> 8); - this.contents[initialContentsOffset++] = (byte) attributeLength; - this.contents[initialContentsOffset++] = (byte) length; - return 1; - } - else { - return 0; - } - } - private int writeArgumentName(char[] name, int modifiers, int oldLength) { - int ensureRoomForBytes = 4; - if (oldLength == 0) { - // Make room for - ensureRoomForBytes += 7; - this.contentsOffset += 7; // Make room for attribute header + count byte - } - if (this.contentsOffset + ensureRoomForBytes > this.contents.length) { - resizeContents(ensureRoomForBytes); - } - int parameterNameIndex = name == null ? 0 : this.constantPool.literalIndex(name); - this.contents[this.contentsOffset++] = (byte) (parameterNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) parameterNameIndex; - int flags = modifiers & (ClassFileConstants.AccFinal | ClassFileConstants.AccSynthetic | ClassFileConstants.AccMandated); - this.contents[this.contentsOffset++] = (byte) (flags >> 8); - this.contents[this.contentsOffset++] = (byte) flags; - return oldLength + 1; - } - - private int generateSignatureAttribute(char[] genericSignature) { - int localContentsOffset = this.contentsOffset; - if (localContentsOffset + 8 >= this.contents.length) { - resizeContents(8); - } - int signatureAttributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.SignatureName); - this.contents[localContentsOffset++] = (byte) (signatureAttributeNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) signatureAttributeNameIndex; - // the length of a signature attribute is equals to 2 - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 2; - int signatureIndex = - this.constantPool.literalIndex(genericSignature); - this.contents[localContentsOffset++] = (byte) (signatureIndex >> 8); - this.contents[localContentsOffset++] = (byte) signatureIndex; - this.contentsOffset = localContentsOffset; - return 1; - } - - private int generateSourceAttribute(String fullFileName) { - int localContentsOffset = this.contentsOffset; - // check that there is enough space to write all the bytes for the field info corresponding - // to the @fieldBinding - if (localContentsOffset + 8 >= this.contents.length) { - resizeContents(8); - } - int sourceAttributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.SourceName); - this.contents[localContentsOffset++] = (byte) (sourceAttributeNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) sourceAttributeNameIndex; - // The length of a source file attribute is 2. This is a fixed-length - // attribute - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 2; - // write the source file name - int fileNameIndex = this.constantPool.literalIndex(fullFileName.toCharArray()); - this.contents[localContentsOffset++] = (byte) (fileNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) fileNameIndex; - this.contentsOffset = localContentsOffset; - return 1; - } - private int generateStackMapAttribute( - MethodBinding methodBinding, - int code_length, - int codeAttributeOffset, - int max_locals, - boolean isClinit) { - int attributesNumber = 0; - int localContentsOffset = this.contentsOffset; - StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream; - stackMapFrameCodeStream.removeFramePosition(code_length); - if (stackMapFrameCodeStream.hasFramePositions()) { - Map frames = new HashMap(); - List realFrames = traverse(isClinit ? null : methodBinding, max_locals, this.contents, codeAttributeOffset + 14, code_length, frames, isClinit); - int numberOfFrames = realFrames.size(); - if (numberOfFrames > 1) { - int stackMapTableAttributeOffset = localContentsOffset; - // add the stack map table attribute - if (localContentsOffset + 8 >= this.contents.length) { - resizeContents(8); - } - int stackMapAttributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.StackMapName); - this.contents[localContentsOffset++] = (byte) (stackMapAttributeNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) stackMapAttributeNameIndex; - - int stackMapAttributeLengthOffset = localContentsOffset; - // generate the attribute - localContentsOffset += 4; - if (localContentsOffset + 4 >= this.contents.length) { - resizeContents(4); - } - int numberOfFramesOffset = localContentsOffset; - localContentsOffset += 2; - if (localContentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - StackMapFrame currentFrame = (StackMapFrame) realFrames.get(0); - for (int j = 1; j < numberOfFrames; j++) { - // select next frame - currentFrame = (StackMapFrame) realFrames.get(j); - // generate current frame - // need to find differences between the current frame and the previous frame - int frameOffset = currentFrame.pc; - // FULL_FRAME - if (localContentsOffset + 5 >= this.contents.length) { - resizeContents(5); - } - this.contents[localContentsOffset++] = (byte) (frameOffset >> 8); - this.contents[localContentsOffset++] = (byte) frameOffset; - int numberOfLocalOffset = localContentsOffset; - localContentsOffset += 2; // leave two spots for number of locals - int numberOfLocalEntries = 0; - int numberOfLocals = currentFrame.getNumberOfLocals(); - int numberOfEntries = 0; - int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length; - for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) { - if (localContentsOffset + 3 >= this.contents.length) { - resizeContents(3); - } - VerificationTypeInfo info = currentFrame.locals[i]; - if (info == null) { - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; - } else { - switch(info.id()) { - case T_boolean : - case T_byte : - case T_char : - case T_int : - case T_short : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; - break; - case T_float : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; - break; - case T_long : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; - i++; - break; - case T_double : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; - i++; - break; - case T_null : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; - break; - default: - this.contents[localContentsOffset++] = (byte) info.tag; - switch (info.tag) { - case VerificationTypeInfo.ITEM_UNINITIALIZED : - int offset = info.offset; - this.contents[localContentsOffset++] = (byte) (offset >> 8); - this.contents[localContentsOffset++] = (byte) offset; - break; - case VerificationTypeInfo.ITEM_OBJECT : - int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); - this.contents[localContentsOffset++] = (byte) (indexForType >> 8); - this.contents[localContentsOffset++] = (byte) indexForType; - } - } - numberOfLocalEntries++; - } - numberOfEntries++; - } - if (localContentsOffset + 4 >= this.contents.length) { - resizeContents(4); - } - this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8); - this.contents[numberOfLocalOffset] = (byte) numberOfEntries; - int numberOfStackItems = currentFrame.numberOfStackItems; - this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8); - this.contents[localContentsOffset++] = (byte) numberOfStackItems; - for (int i = 0; i < numberOfStackItems; i++) { - if (localContentsOffset + 3 >= this.contents.length) { - resizeContents(3); - } - VerificationTypeInfo info = currentFrame.stackItems[i]; - if (info == null) { - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; - } else { - switch(info.id()) { - case T_boolean : - case T_byte : - case T_char : - case T_int : - case T_short : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; - break; - case T_float : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; - break; - case T_long : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; - break; - case T_double : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; - break; - case T_null : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; - break; - default: - this.contents[localContentsOffset++] = (byte) info.tag; - switch (info.tag) { - case VerificationTypeInfo.ITEM_UNINITIALIZED : - int offset = info.offset; - this.contents[localContentsOffset++] = (byte) (offset >> 8); - this.contents[localContentsOffset++] = (byte) offset; - break; - case VerificationTypeInfo.ITEM_OBJECT : - int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); - this.contents[localContentsOffset++] = (byte) (indexForType >> 8); - this.contents[localContentsOffset++] = (byte) indexForType; - } - } - } - } - } - - numberOfFrames--; - if (numberOfFrames != 0) { - this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8); - this.contents[numberOfFramesOffset] = (byte) numberOfFrames; - - int attributeLength = localContentsOffset - stackMapAttributeLengthOffset - 4; - this.contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 24); - this.contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 16); - this.contents[stackMapAttributeLengthOffset++] = (byte) (attributeLength >> 8); - this.contents[stackMapAttributeLengthOffset] = (byte) attributeLength; - attributesNumber++; - } else { - localContentsOffset = stackMapTableAttributeOffset; - } - } - } - this.contentsOffset = localContentsOffset; - return attributesNumber; - } - - private int generateStackMapTableAttribute( - MethodBinding methodBinding, - int code_length, - int codeAttributeOffset, - int max_locals, - boolean isClinit) { - int attributesNumber = 0; - int localContentsOffset = this.contentsOffset; - StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream; - stackMapFrameCodeStream.removeFramePosition(code_length); - if (stackMapFrameCodeStream.hasFramePositions()) { - Map frames = new HashMap(); - List realFrames = traverse(isClinit ? null: methodBinding, max_locals, this.contents, codeAttributeOffset + 14, code_length, frames, isClinit); - int numberOfFrames = realFrames.size(); - if (numberOfFrames > 1) { - int stackMapTableAttributeOffset = localContentsOffset; - // add the stack map table attribute - if (localContentsOffset + 8 >= this.contents.length) { - resizeContents(8); - } - int stackMapTableAttributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.StackMapTableName); - this.contents[localContentsOffset++] = (byte) (stackMapTableAttributeNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) stackMapTableAttributeNameIndex; - - int stackMapTableAttributeLengthOffset = localContentsOffset; - // generate the attribute - localContentsOffset += 4; - if (localContentsOffset + 4 >= this.contents.length) { - resizeContents(4); - } - int numberOfFramesOffset = localContentsOffset; - localContentsOffset += 2; - if (localContentsOffset + 2 >= this.contents.length) { - resizeContents(2); - } - StackMapFrame currentFrame = (StackMapFrame) realFrames.get(0); - StackMapFrame prevFrame = null; - for (int j = 1; j < numberOfFrames; j++) { - // select next frame - prevFrame = currentFrame; - currentFrame = (StackMapFrame) realFrames.get(j); - // generate current frame - // need to find differences between the current frame and the previous frame - int offsetDelta = currentFrame.getOffsetDelta(prevFrame); - switch (currentFrame.getFrameType(prevFrame)) { - case StackMapFrame.APPEND_FRAME : - if (localContentsOffset + 3 >= this.contents.length) { - resizeContents(3); - } - int numberOfDifferentLocals = currentFrame.numberOfDifferentLocals(prevFrame); - this.contents[localContentsOffset++] = (byte) (251 + numberOfDifferentLocals); - this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8); - this.contents[localContentsOffset++] = (byte) offsetDelta; - int index = currentFrame.getIndexOfDifferentLocals(numberOfDifferentLocals); - int numberOfLocals = currentFrame.getNumberOfLocals(); - for (int i = index; i < currentFrame.locals.length && numberOfDifferentLocals > 0; i++) { - if (localContentsOffset + 6 >= this.contents.length) { - resizeContents(6); - } - VerificationTypeInfo info = currentFrame.locals[i]; - if (info == null) { - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; - } else { - switch(info.id()) { - case T_boolean : - case T_byte : - case T_char : - case T_int : - case T_short : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; - break; - case T_float : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; - break; - case T_long : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; - i++; - break; - case T_double : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; - i++; - break; - case T_null : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; - break; - default: - this.contents[localContentsOffset++] = (byte) info.tag; - switch (info.tag) { - case VerificationTypeInfo.ITEM_UNINITIALIZED : - int offset = info.offset; - this.contents[localContentsOffset++] = (byte) (offset >> 8); - this.contents[localContentsOffset++] = (byte) offset; - break; - case VerificationTypeInfo.ITEM_OBJECT : - int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); - this.contents[localContentsOffset++] = (byte) (indexForType >> 8); - this.contents[localContentsOffset++] = (byte) indexForType; - } - } - numberOfDifferentLocals--; - } - } - break; - case StackMapFrame.SAME_FRAME : - if (localContentsOffset + 1 >= this.contents.length) { - resizeContents(1); - } - this.contents[localContentsOffset++] = (byte) offsetDelta; - break; - case StackMapFrame.SAME_FRAME_EXTENDED : - if (localContentsOffset + 3 >= this.contents.length) { - resizeContents(3); - } - this.contents[localContentsOffset++] = (byte) 251; - this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8); - this.contents[localContentsOffset++] = (byte) offsetDelta; - break; - case StackMapFrame.CHOP_FRAME : - if (localContentsOffset + 3 >= this.contents.length) { - resizeContents(3); - } - numberOfDifferentLocals = -currentFrame.numberOfDifferentLocals(prevFrame); - this.contents[localContentsOffset++] = (byte) (251 - numberOfDifferentLocals); - this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8); - this.contents[localContentsOffset++] = (byte) offsetDelta; - break; - case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS : - if (localContentsOffset + 4 >= this.contents.length) { - resizeContents(4); - } - this.contents[localContentsOffset++] = (byte) (offsetDelta + 64); - if (currentFrame.stackItems[0] == null) { - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; - } else { - switch(currentFrame.stackItems[0].id()) { - case T_boolean : - case T_byte : - case T_char : - case T_int : - case T_short : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; - break; - case T_float : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; - break; - case T_long : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; - break; - case T_double : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; - break; - case T_null : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; - break; - default: - VerificationTypeInfo info = currentFrame.stackItems[0]; - byte tag = (byte) info.tag; - this.contents[localContentsOffset++] = tag; - switch (tag) { - case VerificationTypeInfo.ITEM_UNINITIALIZED : - int offset = info.offset; - this.contents[localContentsOffset++] = (byte) (offset >> 8); - this.contents[localContentsOffset++] = (byte) offset; - break; - case VerificationTypeInfo.ITEM_OBJECT : - int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); - this.contents[localContentsOffset++] = (byte) (indexForType >> 8); - this.contents[localContentsOffset++] = (byte) indexForType; - } - } - } - break; - case StackMapFrame.SAME_LOCALS_1_STACK_ITEMS_EXTENDED : - if (localContentsOffset + 6 >= this.contents.length) { - resizeContents(6); - } - this.contents[localContentsOffset++] = (byte) 247; - this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8); - this.contents[localContentsOffset++] = (byte) offsetDelta; - if (currentFrame.stackItems[0] == null) { - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; - } else { - switch(currentFrame.stackItems[0].id()) { - case T_boolean : - case T_byte : - case T_char : - case T_int : - case T_short : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; - break; - case T_float : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; - break; - case T_long : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; - break; - case T_double : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; - break; - case T_null : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; - break; - default: - VerificationTypeInfo info = currentFrame.stackItems[0]; - byte tag = (byte) info.tag; - this.contents[localContentsOffset++] = tag; - switch (tag) { - case VerificationTypeInfo.ITEM_UNINITIALIZED : - int offset = info.offset; - this.contents[localContentsOffset++] = (byte) (offset >> 8); - this.contents[localContentsOffset++] = (byte) offset; - break; - case VerificationTypeInfo.ITEM_OBJECT : - int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); - this.contents[localContentsOffset++] = (byte) (indexForType >> 8); - this.contents[localContentsOffset++] = (byte) indexForType; - } - } - } - break; - default : - // FULL_FRAME - if (localContentsOffset + 5 >= this.contents.length) { - resizeContents(5); - } - this.contents[localContentsOffset++] = (byte) 255; - this.contents[localContentsOffset++] = (byte) (offsetDelta >> 8); - this.contents[localContentsOffset++] = (byte) offsetDelta; - int numberOfLocalOffset = localContentsOffset; - localContentsOffset += 2; // leave two spots for number of locals - int numberOfLocalEntries = 0; - numberOfLocals = currentFrame.getNumberOfLocals(); - int numberOfEntries = 0; - int localsLength = currentFrame.locals == null ? 0 : currentFrame.locals.length; - for (int i = 0; i < localsLength && numberOfLocalEntries < numberOfLocals; i++) { - if (localContentsOffset + 3 >= this.contents.length) { - resizeContents(3); - } - VerificationTypeInfo info = currentFrame.locals[i]; - if (info == null) { - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; - } else { - switch(info.id()) { - case T_boolean : - case T_byte : - case T_char : - case T_int : - case T_short : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; - break; - case T_float : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; - break; - case T_long : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; - i++; - break; - case T_double : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; - i++; - break; - case T_null : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; - break; - default: - this.contents[localContentsOffset++] = (byte) info.tag; - switch (info.tag) { - case VerificationTypeInfo.ITEM_UNINITIALIZED : - int offset = info.offset; - this.contents[localContentsOffset++] = (byte) (offset >> 8); - this.contents[localContentsOffset++] = (byte) offset; - break; - case VerificationTypeInfo.ITEM_OBJECT : - int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); - this.contents[localContentsOffset++] = (byte) (indexForType >> 8); - this.contents[localContentsOffset++] = (byte) indexForType; - } - } - numberOfLocalEntries++; - } - numberOfEntries++; - } - if (localContentsOffset + 4 >= this.contents.length) { - resizeContents(4); - } - this.contents[numberOfLocalOffset++] = (byte) (numberOfEntries >> 8); - this.contents[numberOfLocalOffset] = (byte) numberOfEntries; - int numberOfStackItems = currentFrame.numberOfStackItems; - this.contents[localContentsOffset++] = (byte) (numberOfStackItems >> 8); - this.contents[localContentsOffset++] = (byte) numberOfStackItems; - for (int i = 0; i < numberOfStackItems; i++) { - if (localContentsOffset + 3 >= this.contents.length) { - resizeContents(3); - } - VerificationTypeInfo info = currentFrame.stackItems[i]; - if (info == null) { - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_TOP; - } else { - switch(info.id()) { - case T_boolean : - case T_byte : - case T_char : - case T_int : - case T_short : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_INTEGER; - break; - case T_float : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_FLOAT; - break; - case T_long : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_LONG; - break; - case T_double : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_DOUBLE; - break; - case T_null : - this.contents[localContentsOffset++] = (byte) VerificationTypeInfo.ITEM_NULL; - break; - default: - this.contents[localContentsOffset++] = (byte) info.tag; - switch (info.tag) { - case VerificationTypeInfo.ITEM_UNINITIALIZED : - int offset = info.offset; - this.contents[localContentsOffset++] = (byte) (offset >> 8); - this.contents[localContentsOffset++] = (byte) offset; - break; - case VerificationTypeInfo.ITEM_OBJECT : - int indexForType = this.constantPool.literalIndexForType(info.constantPoolName()); - this.contents[localContentsOffset++] = (byte) (indexForType >> 8); - this.contents[localContentsOffset++] = (byte) indexForType; - } - } - } - } - } - } - - numberOfFrames--; - if (numberOfFrames != 0) { - this.contents[numberOfFramesOffset++] = (byte) (numberOfFrames >> 8); - this.contents[numberOfFramesOffset] = (byte) numberOfFrames; - - int attributeLength = localContentsOffset - stackMapTableAttributeLengthOffset - 4; - this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 24); - this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 16); - this.contents[stackMapTableAttributeLengthOffset++] = (byte) (attributeLength >> 8); - this.contents[stackMapTableAttributeLengthOffset] = (byte) attributeLength; - attributesNumber++; - } else { - localContentsOffset = stackMapTableAttributeOffset; - } - } - } - this.contentsOffset = localContentsOffset; - return attributesNumber; - } - - private int generateSyntheticAttribute() { - int localContentsOffset = this.contentsOffset; - if (localContentsOffset + 6 >= this.contents.length) { - resizeContents(6); - } - int syntheticAttributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.SyntheticName); - this.contents[localContentsOffset++] = (byte) (syntheticAttributeNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) syntheticAttributeNameIndex; - // the length of a synthetic attribute is equals to 0 - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contentsOffset = localContentsOffset; - return 1; - } - - private void generateTypeAnnotation(AnnotationContext annotationContext, int currentOffset) { - Annotation annotation = annotationContext.annotation.getPersistibleAnnotation(); - if (annotation == null || annotation.resolvedType == null) - return; - - int targetType = annotationContext.targetType; - - int[] locations = Annotation.getLocations( - annotationContext.typeReference, - annotationContext.annotation); - - if (this.contentsOffset + 5 >= this.contents.length) { - resizeContents(5); - } - this.contents[this.contentsOffset++] = (byte) targetType; - dumpTargetTypeContents(targetType, annotationContext); - dumpLocations(locations); - generateAnnotation(annotation, currentOffset); - } - - private int generateTypeAnnotationAttributeForTypeDeclaration() { - TypeDeclaration typeDeclaration = this.referenceBinding.scope.referenceContext; - if ((typeDeclaration.bits & ASTNode.HasTypeAnnotations) == 0) { - return 0; - } - int attributesNumber = 0; - int visibleTypeAnnotationsCounter = 0; - int invisibleTypeAnnotationsCounter = 0; - TypeReference superclass = typeDeclaration.superclass; - List allTypeAnnotationContexts = new ArrayList(); - if (superclass != null && (superclass.bits & ASTNode.HasTypeAnnotations) != 0) { - superclass.getAllAnnotationContexts(AnnotationTargetTypeConstants.CLASS_EXTENDS, -1, allTypeAnnotationContexts); - } - TypeReference[] superInterfaces = typeDeclaration.superInterfaces; - if (superInterfaces != null) { - for (int i = 0; i < superInterfaces.length; i++) { - TypeReference superInterface = superInterfaces[i]; - if ((superInterface.bits & ASTNode.HasTypeAnnotations) == 0) { - continue; - } - superInterface.getAllAnnotationContexts(AnnotationTargetTypeConstants.CLASS_EXTENDS, i, allTypeAnnotationContexts); - } - } - TypeParameter[] typeParameters = typeDeclaration.typeParameters; - if (typeParameters != null) { - for (int i = 0, max = typeParameters.length; i < max; i++) { - TypeParameter typeParameter = typeParameters[i]; - if ((typeParameter.bits & ASTNode.HasTypeAnnotations) != 0) { - typeParameter.getAllAnnotationContexts(AnnotationTargetTypeConstants.CLASS_TYPE_PARAMETER, i, allTypeAnnotationContexts); - } - } - } - int size = allTypeAnnotationContexts.size(); - if (size != 0) { - AnnotationContext[] allTypeAnnotationContextsArray = new AnnotationContext[size]; - allTypeAnnotationContexts.toArray(allTypeAnnotationContextsArray); - for (int j = 0, max = allTypeAnnotationContextsArray.length; j < max; j++) { - AnnotationContext annotationContext = allTypeAnnotationContextsArray[j]; - if ((annotationContext.visibility & AnnotationContext.INVISIBLE) != 0) { - invisibleTypeAnnotationsCounter++; - allTypeAnnotationContexts.add(annotationContext); - } else { - visibleTypeAnnotationsCounter++; - allTypeAnnotationContexts.add(annotationContext); - } - } - attributesNumber += generateRuntimeTypeAnnotations( - allTypeAnnotationContextsArray, - visibleTypeAnnotationsCounter, - invisibleTypeAnnotationsCounter); - } - return attributesNumber; - } - - - - - private int generateVarargsAttribute() { - int localContentsOffset = this.contentsOffset; - /* - * handle of the target jsr14 for varargs in the source - * Varargs attribute - * Check that there is enough space to write the attribute - */ - if (localContentsOffset + 6 >= this.contents.length) { - resizeContents(6); - } - int varargsAttributeNameIndex = - this.constantPool.literalIndex(AttributeNamesConstants.VarargsName); - this.contents[localContentsOffset++] = (byte) (varargsAttributeNameIndex >> 8); - this.contents[localContentsOffset++] = (byte) varargsAttributeNameIndex; - // the length of a varargs attribute is equals to 0 - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - this.contents[localContentsOffset++] = 0; - - this.contentsOffset = localContentsOffset; - return 1; - } - - /** - * EXTERNAL API - * Answer the actual bytes of the class file - * - * This method encodes the receiver structure into a byte array which is the content of the classfile. - * Returns the byte array that represents the encoded structure of the receiver. - * - * @return byte[] - */ - public byte[] getBytes() { - if (this.bytes == null) { - this.bytes = new byte[this.headerOffset + this.contentsOffset]; - System.arraycopy(this.header, 0, this.bytes, 0, this.headerOffset); - System.arraycopy(this.contents, 0, this.bytes, this.headerOffset, this.contentsOffset); - } - return this.bytes; - } - /** - * EXTERNAL API - * Answer the compound name of the class file. - * @return char[][] - * e.g. {{java}, {util}, {Hashtable}}. - */ - public char[][] getCompoundName() { - return CharOperation.splitOn('/', fileName()); - } - - private int getParametersCount(char[] methodSignature) { - int i = CharOperation.indexOf('(', methodSignature); - i++; - char currentCharacter = methodSignature[i]; - if (currentCharacter == ')') { - return 0; - } - int result = 0; - while (true) { - currentCharacter = methodSignature[i]; - if (currentCharacter == ')') { - return result; - } - switch (currentCharacter) { - case '[': - // array type - int scanType = scanType(methodSignature, i + 1); - result++; - i = scanType + 1; - break; - case 'L': - scanType = CharOperation.indexOf(';', methodSignature, - i + 1); - result++; - i = scanType + 1; - break; - case 'Z': - case 'B': - case 'C': - case 'D': - case 'F': - case 'I': - case 'J': - case 'S': - result++; - i++; - break; - default: - throw new IllegalArgumentException("Invalid starting type character : " + currentCharacter); //$NON-NLS-1$ - } - } - } - - private char[] getReturnType(char[] methodSignature) { - // skip type parameters - int paren = CharOperation.lastIndexOf(')', methodSignature); - // there could be thrown exceptions behind, thus scan one type exactly - return CharOperation.subarray(methodSignature, paren + 1, - methodSignature.length); - } - - private final int i4At(byte[] reference, int relativeOffset, - int structOffset) { - int position = relativeOffset + structOffset; - return ((reference[position++] & 0xFF) << 24) - + ((reference[position++] & 0xFF) << 16) - + ((reference[position++] & 0xFF) << 8) - + (reference[position] & 0xFF); - } - - protected void initByteArrays() { - int members = this.referenceBinding.methods().length + this.referenceBinding.fields().length; - this.header = new byte[INITIAL_HEADER_SIZE]; - this.contents = new byte[members < 15 ? INITIAL_CONTENTS_SIZE : INITIAL_HEADER_SIZE]; - } - - public void initialize(SourceTypeBinding aType, ClassFile parentClassFile, boolean createProblemType) { - // generate the magic numbers inside the header - this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 24); - this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 16); - this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 8); - this.header[this.headerOffset++] = (byte) (0xCAFEBABEL >> 0); - - long targetVersion = this.targetJDK; - this.header[this.headerOffset++] = (byte) (targetVersion >> 8); // minor high - this.header[this.headerOffset++] = (byte) (targetVersion>> 0); // minor low - this.header[this.headerOffset++] = (byte) (targetVersion >> 24); // major high - this.header[this.headerOffset++] = (byte) (targetVersion >> 16); // major low - - this.constantPoolOffset = this.headerOffset; - this.headerOffset += 2; - this.constantPool.initialize(this); - - // Modifier manipulations for classfile - int accessFlags = aType.getAccessFlags(); - if (aType.isPrivate()) { // rewrite private to non-public - accessFlags &= ~ClassFileConstants.AccPublic; - } - if (aType.isProtected()) { // rewrite protected into public - accessFlags |= ClassFileConstants.AccPublic; - } - // clear all bits that are illegal for a class or an interface - accessFlags - &= ~( - ClassFileConstants.AccStrictfp - | ClassFileConstants.AccProtected - | ClassFileConstants.AccPrivate - | ClassFileConstants.AccStatic - | ClassFileConstants.AccSynchronized - | ClassFileConstants.AccNative); - - // set the AccSuper flag (has to be done after clearing AccSynchronized - since same value) - if (!aType.isInterface()) { // class or enum - accessFlags |= ClassFileConstants.AccSuper; - } - if (aType.isAnonymousType()) { - accessFlags &= ~ClassFileConstants.AccFinal; - } - int finalAbstract = ClassFileConstants.AccFinal | ClassFileConstants.AccAbstract; - if ((accessFlags & finalAbstract) == finalAbstract) { - accessFlags &= ~finalAbstract; - } - this.enclosingClassFile = parentClassFile; - // innerclasses get their names computed at code gen time - - // now we continue to generate the bytes inside the contents array - this.contents[this.contentsOffset++] = (byte) (accessFlags >> 8); - this.contents[this.contentsOffset++] = (byte) accessFlags; - int classNameIndex = this.constantPool.literalIndexForType(aType); - this.contents[this.contentsOffset++] = (byte) (classNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) classNameIndex; - // AspectJ Extension - don't include result of decp weaving in the class created by compilation - /*old{ - int superclassNameIndex; - if (aType.isInterface()) { - superclassNameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName); - } else { - if (aType.superclass != null) { - if ((aType.superclass.tagBits & TagBits.HasMissingType) != 0) { - superclassNameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName); - } else { - superclassNameIndex = this.constantPool.literalIndexForType(aType.superclass); - } - } else { - superclassNameIndex = 0; - } - } - }new:*/ - ReferenceBinding superclass = aType.superclass; - int superclassNameIndex; - if (aType.originalSuperclass!=null) { - superclass = aType.originalSuperclass; - } - if (aType.isInterface()) { - superclassNameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName); - } else { - if (superclass != null) { - if ((superclass.tagBits & TagBits.HasMissingType) != 0) { - superclassNameIndex = this.constantPool.literalIndexForType(ConstantPool.JavaLangObjectConstantPoolName); - } else { - superclassNameIndex = this.constantPool.literalIndexForType(superclass); - } - } else { - superclassNameIndex = 0; - } - } - // AspectJ Extension end - this.contents[this.contentsOffset++] = (byte) (superclassNameIndex >> 8); - this.contents[this.contentsOffset++] = (byte) superclassNameIndex; - ReferenceBinding[] superInterfacesBinding = aType.superInterfaces(); - // AspectJ Extension - don't include result of decp weaving in the class created by compilaton - if (aType.originalSuperInterfaces!=null) { - superInterfacesBinding = aType.originalSuperInterfaces; - } - // AspectJ Extension end - int interfacesCount = superInterfacesBinding.length; - int interfacesCountPosition = this.contentsOffset; - this.contentsOffset += 2; - int interfaceCounter = 0; - for (int i = 0; i < interfacesCount; i++) { - ReferenceBinding binding = superInterfacesBinding[i]; - if ((binding.tagBits & TagBits.HasMissingType) != 0) { - continue; - } - interfaceCounter++; - int interfaceIndex = this.constantPool.literalIndexForType(binding); - this.contents[this.contentsOffset++] = (byte) (interfaceIndex >> 8); - this.contents[this.contentsOffset++] = (byte) interfaceIndex; - } - this.contents[interfacesCountPosition++] = (byte) (interfaceCounter >> 8); - this.contents[interfacesCountPosition] = (byte) interfaceCounter; - this.creatingProblemType = createProblemType; - - // retrieve the enclosing one guaranteed to be the one matching the propagated flow info - // 1FF9ZBU: LFCOM:ALL - Local variable attributes busted (Sanity check) - this.codeStream.maxFieldCount = aType.scope.outerMostClassScope().referenceType().maxFieldCount; - } - - private void initializeDefaultLocals(StackMapFrame frame, - MethodBinding methodBinding, - int maxLocals, - int codeLength) { - if (maxLocals != 0) { - int resolvedPosition = 0; - // take into account enum constructor synthetic name+ordinal - final boolean isConstructor = methodBinding.isConstructor(); - if (isConstructor || !methodBinding.isStatic()) { - LocalVariableBinding localVariableBinding = new LocalVariableBinding(ConstantPool.This, methodBinding.declaringClass, 0, false); - localVariableBinding.resolvedPosition = 0; - this.codeStream.record(localVariableBinding); - localVariableBinding.recordInitializationStartPC(0); - localVariableBinding.recordInitializationEndPC(codeLength); - frame.putLocal(resolvedPosition, new VerificationTypeInfo( - isConstructor ? VerificationTypeInfo.ITEM_UNINITIALIZED_THIS : VerificationTypeInfo.ITEM_OBJECT, - methodBinding.declaringClass)); - resolvedPosition++; - } - - if (isConstructor) { - if (methodBinding.declaringClass.isEnum()) { - LocalVariableBinding localVariableBinding = new LocalVariableBinding(" name".toCharArray(), this.referenceBinding.scope.getJavaLangString(), 0, false); //$NON-NLS-1$ - localVariableBinding.resolvedPosition = resolvedPosition; - this.codeStream.record(localVariableBinding); - localVariableBinding.recordInitializationStartPC(0); - localVariableBinding.recordInitializationEndPC(codeLength); - - frame.putLocal(resolvedPosition, new VerificationTypeInfo( - TypeIds.T_JavaLangString, - ConstantPool.JavaLangStringConstantPoolName)); - resolvedPosition++; - - localVariableBinding = new LocalVariableBinding(" ordinal".toCharArray(), TypeBinding.INT, 0, false); //$NON-NLS-1$ - localVariableBinding.resolvedPosition = resolvedPosition; - this.codeStream.record(localVariableBinding); - localVariableBinding.recordInitializationStartPC(0); - localVariableBinding.recordInitializationEndPC(codeLength); - frame.putLocal(resolvedPosition, new VerificationTypeInfo( - TypeBinding.INT)); - resolvedPosition++; - } - - // take into account the synthetic parameters - if (methodBinding.declaringClass.isNestedType()) { - ReferenceBinding enclosingInstanceTypes[]; - if ((enclosingInstanceTypes = methodBinding.declaringClass.syntheticEnclosingInstanceTypes()) != null) { - for (int i = 0, max = enclosingInstanceTypes.length; i < max; i++) { - // an enclosingInstanceType can only be a reference - // binding. It cannot be - // LongBinding or DoubleBinding - LocalVariableBinding localVariableBinding = new LocalVariableBinding((" enclosingType" + i).toCharArray(), enclosingInstanceTypes[i], 0, false); //$NON-NLS-1$ - localVariableBinding.resolvedPosition = resolvedPosition; - this.codeStream.record(localVariableBinding); - localVariableBinding.recordInitializationStartPC(0); - localVariableBinding.recordInitializationEndPC(codeLength); - - frame.putLocal(resolvedPosition, - new VerificationTypeInfo(enclosingInstanceTypes[i])); - resolvedPosition++; - } - } - - TypeBinding[] arguments; - if ((arguments = methodBinding.parameters) != null) { - for (int i = 0, max = arguments.length; i < max; i++) { - final TypeBinding typeBinding = arguments[i]; - frame.putLocal(resolvedPosition, - new VerificationTypeInfo(typeBinding)); - switch (typeBinding.id) { - case TypeIds.T_double: - case TypeIds.T_long: - resolvedPosition += 2; - break; - default: - resolvedPosition++; - } - } - } - - SyntheticArgumentBinding syntheticArguments[]; - if ((syntheticArguments = methodBinding.declaringClass.syntheticOuterLocalVariables()) != null) { - for (int i = 0, max = syntheticArguments.length; i < max; i++) { - final TypeBinding typeBinding = syntheticArguments[i].type; - LocalVariableBinding localVariableBinding = new LocalVariableBinding((" synthetic" + i).toCharArray(), typeBinding, 0, false); //$NON-NLS-1$ - localVariableBinding.resolvedPosition = resolvedPosition; - this.codeStream.record(localVariableBinding); - localVariableBinding.recordInitializationStartPC(0); - localVariableBinding.recordInitializationEndPC(codeLength); - - frame.putLocal(resolvedPosition, - new VerificationTypeInfo(typeBinding)); - switch (typeBinding.id) { - case TypeIds.T_double: - case TypeIds.T_long: - resolvedPosition += 2; - break; - default: - resolvedPosition++; - } - } - } - } else { - TypeBinding[] arguments; - if ((arguments = methodBinding.parameters) != null) { - for (int i = 0, max = arguments.length; i < max; i++) { - final TypeBinding typeBinding = arguments[i]; - frame.putLocal(resolvedPosition, - new VerificationTypeInfo(typeBinding)); - switch (typeBinding.id) { - case TypeIds.T_double: - case TypeIds.T_long: - resolvedPosition += 2; - break; - default: - resolvedPosition++; - } - } - } - } - } else { - TypeBinding[] arguments; - if ((arguments = methodBinding.parameters) != null) { - for (int i = 0, max = arguments.length; i < max; i++) { - final TypeBinding typeBinding = arguments[i]; - // For the branching complexities in the generated $deserializeLambda$ we need the local variable - LocalVariableBinding localVariableBinding = new LocalVariableBinding((" synthetic"+i).toCharArray(), typeBinding, 0, true); //$NON-NLS-1$ - localVariableBinding.resolvedPosition = i; - this.codeStream.record(localVariableBinding); - localVariableBinding.recordInitializationStartPC(0); - localVariableBinding.recordInitializationEndPC(codeLength); - frame.putLocal(resolvedPosition, - new VerificationTypeInfo(typeBinding)); - switch (typeBinding.id) { - case TypeIds.T_double: - case TypeIds.T_long: - resolvedPosition += 2; - break; - default: - resolvedPosition++; - } - } - } - } - } - } - - private void initializeLocals(boolean isStatic, int currentPC, StackMapFrame currentFrame) { - VerificationTypeInfo[] locals = currentFrame.locals; - int localsLength = locals.length; - int i = 0; - if (!isStatic) { - // we don't want to reset the first local if the method is not static - i = 1; - } - for (; i < localsLength; i++) { - locals[i] = null; - } - i = 0; - locals: for (int max = this.codeStream.allLocalsCounter; i < max; i++) { - LocalVariableBinding localVariable = this.codeStream.locals[i]; - if (localVariable == null) continue; - int resolvedPosition = localVariable.resolvedPosition; - final TypeBinding localVariableTypeBinding = localVariable.type; - inits: for (int j = 0; j < localVariable.initializationCount; j++) { - int startPC = localVariable.initializationPCs[j << 1]; - int endPC = localVariable.initializationPCs[(j << 1) + 1]; - if (currentPC < startPC) { - continue inits; - } else if (currentPC < endPC) { - // the current local is an active local - if (currentFrame.locals[resolvedPosition] == null) { - currentFrame.locals[resolvedPosition] = - new VerificationTypeInfo( - localVariableTypeBinding); - } - continue locals; - } - } - } - } - /** - * INTERNAL USE-ONLY - * Returns the most enclosing classfile of the receiver. This is used know to store the constant pool name - * for all inner types of the receiver. - * @return org.aspectj.org.eclipse.jdt.internal.compiler.codegen.ClassFile - */ - public ClassFile outerMostEnclosingClassFile() { - ClassFile current = this; - while (current.enclosingClassFile != null) - current = current.enclosingClassFile; - return current; - } - - public void recordInnerClasses(TypeBinding binding) { - if (this.innerClassesBindings == null) { - this.innerClassesBindings = new HashSet(INNER_CLASSES_SIZE); - } - ReferenceBinding innerClass = (ReferenceBinding) binding; - this.innerClassesBindings.add(innerClass.erasure().unannotated(false)); // should not emit yet another inner class for Outer.@Inner Inner. - ReferenceBinding enclosingType = innerClass.enclosingType(); - while (enclosingType != null - && enclosingType.isNestedType()) { - this.innerClassesBindings.add(enclosingType.erasure().unannotated(false)); - enclosingType = enclosingType.enclosingType(); - } - } - - public int recordBootstrapMethod(FunctionalExpression expression) { - if (this.bootstrapMethods == null) { - this.bootstrapMethods = new ArrayList(); - } - this.bootstrapMethods.add(expression); - // Record which bootstrap method was assigned to the expression - expression.bootstrapMethodNumber = this.bootstrapMethods.size() - 1; - return this.bootstrapMethods.size() - 1; - } - - public void reset(SourceTypeBinding typeBinding) { - // the code stream is reinitialized for each method - final CompilerOptions options = typeBinding.scope.compilerOptions(); - this.referenceBinding = typeBinding; - this.isNestedType = typeBinding.isNestedType(); - this.targetJDK = options.targetJDK; - this.produceAttributes = options.produceDebugAttributes; - if (this.targetJDK >= ClassFileConstants.JDK1_6) { - this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP_TABLE; - if (this.targetJDK >= ClassFileConstants.JDK1_8) { - this.produceAttributes |= ClassFileConstants.ATTR_TYPE_ANNOTATION; - if (options.produceMethodParameters) { - this.produceAttributes |= ClassFileConstants.ATTR_METHOD_PARAMETERS; - } - } - } else if (this.targetJDK == ClassFileConstants.CLDC_1_1) { - this.targetJDK = ClassFileConstants.JDK1_1; // put back 45.3 - this.produceAttributes |= ClassFileConstants.ATTR_STACK_MAP; - } - this.bytes = null; - this.constantPool.reset(); - this.codeStream.reset(this); - this.constantPoolOffset = 0; - this.contentsOffset = 0; - this.creatingProblemType = false; - this.enclosingClassFile = null; - this.headerOffset = 0; - this.methodCount = 0; - this.methodCountOffset = 0; - if (this.innerClassesBindings != null) { - this.innerClassesBindings.clear(); - } - if (this.bootstrapMethods != null) { - this.bootstrapMethods.clear(); - } - this.missingTypes = null; - this.visitedTypes = null; - } - - /** - * Resize the pool contents - */ - private final void resizeContents(int minimalSize) { - int length = this.contents.length; - int toAdd = length; - if (toAdd < minimalSize) - toAdd = minimalSize; - System.arraycopy(this.contents, 0, this.contents = new byte[length + toAdd], 0, length); - } - - private VerificationTypeInfo retrieveLocal(int currentPC, int resolvedPosition) { - for (int i = 0, max = this.codeStream.allLocalsCounter; i < max; i++) { - LocalVariableBinding localVariable = this.codeStream.locals[i]; - if (localVariable == null) continue; - if (resolvedPosition == localVariable.resolvedPosition) { - inits: for (int j = 0; j < localVariable.initializationCount; j++) { - int startPC = localVariable.initializationPCs[j << 1]; - int endPC = localVariable.initializationPCs[(j << 1) + 1]; - if (currentPC < startPC) { - continue inits; - } else if (currentPC < endPC) { - // the current local is an active local - return new VerificationTypeInfo(localVariable.type); - } - } - } - } - return null; - } - - private int scanType(char[] methodSignature, int index) { - switch (methodSignature[index]) { - case '[': - // array type - return scanType(methodSignature, index + 1); - case 'L': - return CharOperation.indexOf(';', methodSignature, index + 1); - case 'Z': - case 'B': - case 'C': - case 'D': - case 'F': - case 'I': - case 'J': - case 'S': - return index; - default: - throw new IllegalArgumentException(); - } - } - - /** - * INTERNAL USE-ONLY - * This methods leaves the space for method counts recording. - */ - public void setForMethodInfos() { - // leave some space for the methodCount - this.methodCountOffset = this.contentsOffset; - this.contentsOffset += 2; - } - - private List filterFakeFrames(Set realJumpTargets, Map frames, int codeLength) { - // no more frame to generate - // filter out "fake" frames - realJumpTargets.remove(new Integer(codeLength)); - List result = new ArrayList(); - for (Iterator iterator = realJumpTargets.iterator(); iterator.hasNext(); ) { - Integer jumpTarget = (Integer) iterator.next(); - StackMapFrame frame = (StackMapFrame) frames.get(jumpTarget); - if (frame != null) { - result.add(frame); - } - } - Collections.sort(result, new Comparator() { - public int compare(Object o1, Object o2) { - StackMapFrame frame = (StackMapFrame) o1; - StackMapFrame frame2 = (StackMapFrame) o2; - return frame.pc - frame2.pc; - } - }); - return result; - } - - public List traverse(MethodBinding methodBinding, int maxLocals, byte[] bytecodes, int codeOffset, int codeLength, Map frames, boolean isClinit) { - Set realJumpTarget = new HashSet(); - - StackMapFrameCodeStream stackMapFrameCodeStream = (StackMapFrameCodeStream) this.codeStream; - int[] framePositions = stackMapFrameCodeStream.getFramePositions(); - int pc = codeOffset; - int index; - int[] constantPoolOffsets = this.constantPool.offsets; - byte[] poolContents = this.constantPool.poolContent; - - // set initial values for frame positions - int indexInFramePositions = 0; - int framePositionsLength = framePositions.length; - int currentFramePosition = framePositions[0]; - - // set initial values for stack depth markers - int indexInStackDepthMarkers = 0; - StackDepthMarker[] stackDepthMarkers = stackMapFrameCodeStream.getStackDepthMarkers(); - int stackDepthMarkersLength = stackDepthMarkers == null ? 0 : stackDepthMarkers.length; - boolean hasStackDepthMarkers = stackDepthMarkersLength != 0; - StackDepthMarker stackDepthMarker = null; - if (hasStackDepthMarkers) { - stackDepthMarker = stackDepthMarkers[0]; - } - - // set initial values for stack markers (used only in cldc mode) - int indexInStackMarkers = 0; - StackMarker[] stackMarkers = stackMapFrameCodeStream.getStackMarkers(); - int stackMarkersLength = stackMarkers == null ? 0 : stackMarkers.length; - boolean hasStackMarkers = stackMarkersLength != 0; - StackMarker stackMarker = null; - if (hasStackMarkers) { - stackMarker = stackMarkers[0]; - } - - // set initial values for exception markers - int indexInExceptionMarkers = 0; - ExceptionMarker[] exceptionMarkers= stackMapFrameCodeStream.getExceptionMarkers(); - int exceptionsMarkersLength = exceptionMarkers == null ? 0 : exceptionMarkers.length; - boolean hasExceptionMarkers = exceptionsMarkersLength != 0; - ExceptionMarker exceptionMarker = null; - if (hasExceptionMarkers) { - exceptionMarker = exceptionMarkers[0]; - } - - StackMapFrame frame = new StackMapFrame(maxLocals); - if (!isClinit) { - initializeDefaultLocals(frame, methodBinding, maxLocals, codeLength); - } - frame.pc = -1; - add(frames, frame.duplicate()); - addRealJumpTarget(realJumpTarget, -1); - for (int i = 0, max = this.codeStream.exceptionLabelsCounter; i < max; i++) { - ExceptionLabel exceptionLabel = this.codeStream.exceptionLabels[i]; - if (exceptionLabel != null) { - addRealJumpTarget(realJumpTarget, exceptionLabel.position); - } - } - while (true) { - int currentPC = pc - codeOffset; - if (hasStackMarkers && stackMarker.pc == currentPC) { - VerificationTypeInfo[] infos = frame.stackItems; - VerificationTypeInfo[] tempInfos = new VerificationTypeInfo[frame.numberOfStackItems]; - System.arraycopy(infos, 0, tempInfos, 0, frame.numberOfStackItems); - stackMarker.setInfos(tempInfos); - } else if (hasStackMarkers && stackMarker.destinationPC == currentPC) { - VerificationTypeInfo[] infos = stackMarker.infos; - frame.stackItems = infos; - frame.numberOfStackItems = infos.length; - indexInStackMarkers++; - if (indexInStackMarkers < stackMarkersLength) { - stackMarker = stackMarkers[indexInStackMarkers]; - } else { - hasStackMarkers = false; - } - } - if (hasStackDepthMarkers && stackDepthMarker.pc == currentPC) { - TypeBinding typeBinding = stackDepthMarker.typeBinding; - if (typeBinding != null) { - if (stackDepthMarker.delta > 0) { - frame.addStackItem(new VerificationTypeInfo(typeBinding)); - } else { - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(typeBinding); - } - } else { - frame.numberOfStackItems--; - } - indexInStackDepthMarkers++; - if (indexInStackDepthMarkers < stackDepthMarkersLength) { - stackDepthMarker = stackDepthMarkers[indexInStackDepthMarkers]; - } else { - hasStackDepthMarkers = false; - } - } - if (hasExceptionMarkers && exceptionMarker.pc == currentPC) { - frame.numberOfStackItems = 0; - frame.addStackItem(new VerificationTypeInfo(0, VerificationTypeInfo.ITEM_OBJECT, exceptionMarker.constantPoolName)); - indexInExceptionMarkers++; - if (indexInExceptionMarkers < exceptionsMarkersLength) { - exceptionMarker = exceptionMarkers[indexInExceptionMarkers]; - } else { - hasExceptionMarkers = false; - } - } - if (currentFramePosition < currentPC) { - do { - indexInFramePositions++; - if (indexInFramePositions < framePositionsLength) { - currentFramePosition = framePositions[indexInFramePositions]; - } else { - currentFramePosition = Integer.MAX_VALUE; - } - } while (currentFramePosition < currentPC); - } - if (currentFramePosition == currentPC) { - // need to build a new frame and create a stack map attribute entry - StackMapFrame currentFrame = frame.duplicate(); - currentFrame.pc = currentPC; - // initialize locals - initializeLocals(isClinit ? true : methodBinding.isStatic(), currentPC, currentFrame); - // insert a new frame - add(frames, currentFrame); - indexInFramePositions++; - if (indexInFramePositions < framePositionsLength) { - currentFramePosition = framePositions[indexInFramePositions]; - } else { - currentFramePosition = Integer.MAX_VALUE; - } - } - byte opcode = (byte) u1At(bytecodes, 0, pc); - switch (opcode) { - case Opcodes.OPC_nop: - pc++; - break; - case Opcodes.OPC_aconst_null: - frame.addStackItem(TypeBinding.NULL); - pc++; - break; - case Opcodes.OPC_iconst_m1: - case Opcodes.OPC_iconst_0: - case Opcodes.OPC_iconst_1: - case Opcodes.OPC_iconst_2: - case Opcodes.OPC_iconst_3: - case Opcodes.OPC_iconst_4: - case Opcodes.OPC_iconst_5: - frame.addStackItem(TypeBinding.INT); - pc++; - break; - case Opcodes.OPC_lconst_0: - case Opcodes.OPC_lconst_1: - frame.addStackItem(TypeBinding.LONG); - pc++; - break; - case Opcodes.OPC_fconst_0: - case Opcodes.OPC_fconst_1: - case Opcodes.OPC_fconst_2: - frame.addStackItem(TypeBinding.FLOAT); - pc++; - break; - case Opcodes.OPC_dconst_0: - case Opcodes.OPC_dconst_1: - frame.addStackItem(TypeBinding.DOUBLE); - pc++; - break; - case Opcodes.OPC_bipush: - frame.addStackItem(TypeBinding.BYTE); - pc += 2; - break; - case Opcodes.OPC_sipush: - frame.addStackItem(TypeBinding.SHORT); - pc += 3; - break; - case Opcodes.OPC_ldc: - index = u1At(bytecodes, 1, pc); - switch (u1At(poolContents, 0, constantPoolOffsets[index])) { - case ClassFileConstants.StringTag: - frame - .addStackItem(new VerificationTypeInfo( - TypeIds.T_JavaLangString, - ConstantPool.JavaLangStringConstantPoolName)); - break; - case ClassFileConstants.IntegerTag: - frame.addStackItem(TypeBinding.INT); - break; - case ClassFileConstants.FloatTag: - frame.addStackItem(TypeBinding.FLOAT); - break; - case ClassFileConstants.ClassTag: - frame.addStackItem(new VerificationTypeInfo( - TypeIds.T_JavaLangClass, - ConstantPool.JavaLangClassConstantPoolName)); - } - pc += 2; - break; - case Opcodes.OPC_ldc_w: - index = u2At(bytecodes, 1, pc); - switch (u1At(poolContents, 0, constantPoolOffsets[index])) { - case ClassFileConstants.StringTag: - frame - .addStackItem(new VerificationTypeInfo( - TypeIds.T_JavaLangString, - ConstantPool.JavaLangStringConstantPoolName)); - break; - case ClassFileConstants.IntegerTag: - frame.addStackItem(TypeBinding.INT); - break; - case ClassFileConstants.FloatTag: - frame.addStackItem(TypeBinding.FLOAT); - break; - case ClassFileConstants.ClassTag: - frame.addStackItem(new VerificationTypeInfo( - TypeIds.T_JavaLangClass, - ConstantPool.JavaLangClassConstantPoolName)); - } - pc += 3; - break; - case Opcodes.OPC_ldc2_w: - index = u2At(bytecodes, 1, pc); - switch (u1At(poolContents, 0, constantPoolOffsets[index])) { - case ClassFileConstants.DoubleTag: - frame.addStackItem(TypeBinding.DOUBLE); - break; - case ClassFileConstants.LongTag: - frame.addStackItem(TypeBinding.LONG); - break; - } - pc += 3; - break; - case Opcodes.OPC_iload: - frame.addStackItem(TypeBinding.INT); - pc += 2; - break; - case Opcodes.OPC_lload: - frame.addStackItem(TypeBinding.LONG); - pc += 2; - break; - case Opcodes.OPC_fload: - frame.addStackItem(TypeBinding.FLOAT); - pc += 2; - break; - case Opcodes.OPC_dload: - frame.addStackItem(TypeBinding.DOUBLE); - pc += 2; - break; - case Opcodes.OPC_aload: - index = u1At(bytecodes, 1, pc); - VerificationTypeInfo localsN = retrieveLocal(currentPC, index); - frame.addStackItem(localsN); - pc += 2; - break; - case Opcodes.OPC_iload_0: - case Opcodes.OPC_iload_1: - case Opcodes.OPC_iload_2: - case Opcodes.OPC_iload_3: - frame.addStackItem(TypeBinding.INT); - pc++; - break; - case Opcodes.OPC_lload_0: - case Opcodes.OPC_lload_1: - case Opcodes.OPC_lload_2: - case Opcodes.OPC_lload_3: - frame.addStackItem(TypeBinding.LONG); - pc++; - break; - case Opcodes.OPC_fload_0: - case Opcodes.OPC_fload_1: - case Opcodes.OPC_fload_2: - case Opcodes.OPC_fload_3: - frame.addStackItem(TypeBinding.FLOAT); - pc++; - break; - case Opcodes.OPC_dload_0: - case Opcodes.OPC_dload_1: - case Opcodes.OPC_dload_2: - case Opcodes.OPC_dload_3: - frame.addStackItem(TypeBinding.DOUBLE); - pc++; - break; - case Opcodes.OPC_aload_0: - VerificationTypeInfo locals0 = frame.locals[0]; - if (locals0 == null || locals0.tag != VerificationTypeInfo.ITEM_UNINITIALIZED_THIS) { - // special case to handle uninitialized object - locals0 = retrieveLocal(currentPC, 0); - } - frame.addStackItem(locals0); - pc++; - break; - case Opcodes.OPC_aload_1: - VerificationTypeInfo locals1 = retrieveLocal(currentPC, 1); - frame.addStackItem(locals1); - pc++; - break; - case Opcodes.OPC_aload_2: - VerificationTypeInfo locals2 = retrieveLocal(currentPC, 2); - frame.addStackItem(locals2); - pc++; - break; - case Opcodes.OPC_aload_3: - VerificationTypeInfo locals3 = retrieveLocal(currentPC, 3); - frame.addStackItem(locals3); - pc++; - break; - case Opcodes.OPC_iaload: - frame.numberOfStackItems -=2; - frame.addStackItem(TypeBinding.INT); - pc++; - break; - case Opcodes.OPC_laload: - frame.numberOfStackItems -=2; - frame.addStackItem(TypeBinding.LONG); - pc++; - break; - case Opcodes.OPC_faload: - frame.numberOfStackItems -=2; - frame.addStackItem(TypeBinding.FLOAT); - pc++; - break; - case Opcodes.OPC_daload: - frame.numberOfStackItems -=2; - frame.addStackItem(TypeBinding.DOUBLE); - pc++; - break; - case Opcodes.OPC_aaload: - frame.numberOfStackItems--; - frame.replaceWithElementType(); - pc++; - break; - case Opcodes.OPC_baload: - frame.numberOfStackItems -=2; - frame.addStackItem(TypeBinding.BYTE); - pc++; - break; - case Opcodes.OPC_caload: - frame.numberOfStackItems -=2; - frame.addStackItem(TypeBinding.CHAR); - pc++; - break; - case Opcodes.OPC_saload: - frame.numberOfStackItems -=2; - frame.addStackItem(TypeBinding.SHORT); - pc++; - break; - case Opcodes.OPC_istore: - case Opcodes.OPC_lstore: - case Opcodes.OPC_fstore: - case Opcodes.OPC_dstore: - frame.numberOfStackItems--; - pc += 2; - break; - case Opcodes.OPC_astore: - index = u1At(bytecodes, 1, pc); - frame.numberOfStackItems--; - pc += 2; - break; - case Opcodes.OPC_astore_0: - frame.locals[0] = frame.stackItems[frame.numberOfStackItems - 1]; - frame.numberOfStackItems--; - pc++; - break; - case Opcodes.OPC_astore_1: - case Opcodes.OPC_astore_2: - case Opcodes.OPC_astore_3: - case Opcodes.OPC_istore_0: - case Opcodes.OPC_istore_1: - case Opcodes.OPC_istore_2: - case Opcodes.OPC_istore_3: - case Opcodes.OPC_lstore_0: - case Opcodes.OPC_lstore_1: - case Opcodes.OPC_lstore_2: - case Opcodes.OPC_lstore_3: - case Opcodes.OPC_fstore_0: - case Opcodes.OPC_fstore_1: - case Opcodes.OPC_fstore_2: - case Opcodes.OPC_fstore_3: - case Opcodes.OPC_dstore_0: - case Opcodes.OPC_dstore_1: - case Opcodes.OPC_dstore_2: - case Opcodes.OPC_dstore_3: - frame.numberOfStackItems--; - pc++; - break; - case Opcodes.OPC_iastore: - case Opcodes.OPC_lastore: - case Opcodes.OPC_fastore: - case Opcodes.OPC_dastore: - case Opcodes.OPC_aastore: - case Opcodes.OPC_bastore: - case Opcodes.OPC_castore: - case Opcodes.OPC_sastore: - frame.numberOfStackItems-=3; - pc++; - break; - case Opcodes.OPC_pop: - frame.numberOfStackItems--; - pc++; - break; - case Opcodes.OPC_pop2: - int numberOfStackItems = frame.numberOfStackItems; - switch(frame.stackItems[numberOfStackItems - 1].id()) { - case TypeIds.T_long : - case TypeIds.T_double : - frame.numberOfStackItems--; - break; - default: - frame.numberOfStackItems -= 2; - } - pc++; - break; - case Opcodes.OPC_dup: - frame.addStackItem(frame.stackItems[frame.numberOfStackItems - 1]); - pc++; - break; - case Opcodes.OPC_dup_x1: - VerificationTypeInfo info = frame.stackItems[frame.numberOfStackItems - 1]; - frame.numberOfStackItems--; - VerificationTypeInfo info2 = frame.stackItems[frame.numberOfStackItems - 1]; - frame.numberOfStackItems--; - frame.addStackItem(info); - frame.addStackItem(info2); - frame.addStackItem(info); - pc++; - break; - case Opcodes.OPC_dup_x2: - info = frame.stackItems[frame.numberOfStackItems - 1]; - frame.numberOfStackItems--; - info2 = frame.stackItems[frame.numberOfStackItems - 1]; - frame.numberOfStackItems--; - switch(info2.id()) { - case TypeIds.T_long : - case TypeIds.T_double : - frame.addStackItem(info); - frame.addStackItem(info2); - frame.addStackItem(info); - break; - default: - numberOfStackItems = frame.numberOfStackItems; - VerificationTypeInfo info3 = frame.stackItems[numberOfStackItems - 1]; - frame.numberOfStackItems--; - frame.addStackItem(info); - frame.addStackItem(info3); - frame.addStackItem(info2); - frame.addStackItem(info); - } - pc++; - break; - case Opcodes.OPC_dup2: - info = frame.stackItems[frame.numberOfStackItems - 1]; - frame.numberOfStackItems--; - switch(info.id()) { - case TypeIds.T_double : - case TypeIds.T_long : - frame.addStackItem(info); - frame.addStackItem(info); - break; - default: - info2 = frame.stackItems[frame.numberOfStackItems - 1]; - frame.numberOfStackItems--; - frame.addStackItem(info2); - frame.addStackItem(info); - frame.addStackItem(info2); - frame.addStackItem(info); - } - pc++; - break; - case Opcodes.OPC_dup2_x1: - info = frame.stackItems[frame.numberOfStackItems - 1]; - frame.numberOfStackItems--; - info2 = frame.stackItems[frame.numberOfStackItems - 1]; - frame.numberOfStackItems--; - switch(info.id()) { - case TypeIds.T_double : - case TypeIds.T_long : - frame.addStackItem(info); - frame.addStackItem(info2); - frame.addStackItem(info); - break; - default: - VerificationTypeInfo info3 = frame.stackItems[frame.numberOfStackItems - 1]; - frame.numberOfStackItems--; - frame.addStackItem(info2); - frame.addStackItem(info); - frame.addStackItem(info3); - frame.addStackItem(info2); - frame.addStackItem(info); - } - pc++; - break; - case Opcodes.OPC_dup2_x2: - numberOfStackItems = frame.numberOfStackItems; - info = frame.stackItems[numberOfStackItems - 1]; - frame.numberOfStackItems--; - info2 = frame.stackItems[frame.numberOfStackItems - 1]; - frame.numberOfStackItems--; - switch(info.id()) { - case TypeIds.T_long : - case TypeIds.T_double : - switch(info2.id()) { - case TypeIds.T_long : - case TypeIds.T_double : - // form 4 - frame.addStackItem(info); - frame.addStackItem(info2); - frame.addStackItem(info); - break; - default: - // form 2 - numberOfStackItems = frame.numberOfStackItems; - VerificationTypeInfo info3 = frame.stackItems[numberOfStackItems - 1]; - frame.numberOfStackItems--; - frame.addStackItem(info); - frame.addStackItem(info3); - frame.addStackItem(info2); - frame.addStackItem(info); - } - break; - default: - numberOfStackItems = frame.numberOfStackItems; - VerificationTypeInfo info3 = frame.stackItems[numberOfStackItems - 1]; - frame.numberOfStackItems--; - switch(info3.id()) { - case TypeIds.T_long : - case TypeIds.T_double : - // form 3 - frame.addStackItem(info2); - frame.addStackItem(info); - frame.addStackItem(info3); - frame.addStackItem(info2); - frame.addStackItem(info); - break; - default: - // form 1 - numberOfStackItems = frame.numberOfStackItems; - VerificationTypeInfo info4 = frame.stackItems[numberOfStackItems - 1]; - frame.numberOfStackItems--; - frame.addStackItem(info2); - frame.addStackItem(info); - frame.addStackItem(info4); - frame.addStackItem(info3); - frame.addStackItem(info2); - frame.addStackItem(info); - } - } - pc++; - break; - case Opcodes.OPC_swap: - numberOfStackItems = frame.numberOfStackItems; - info = frame.stackItems[numberOfStackItems - 1]; - info2 = frame.stackItems[numberOfStackItems - 2]; - frame.stackItems[numberOfStackItems - 1] = info2; - frame.stackItems[numberOfStackItems - 2] = info; - pc++; - break; - case Opcodes.OPC_iadd: - case Opcodes.OPC_ladd: - case Opcodes.OPC_fadd: - case Opcodes.OPC_dadd: - case Opcodes.OPC_isub: - case Opcodes.OPC_lsub: - case Opcodes.OPC_fsub: - case Opcodes.OPC_dsub: - case Opcodes.OPC_imul: - case Opcodes.OPC_lmul: - case Opcodes.OPC_fmul: - case Opcodes.OPC_dmul: - case Opcodes.OPC_idiv: - case Opcodes.OPC_ldiv: - case Opcodes.OPC_fdiv: - case Opcodes.OPC_ddiv: - case Opcodes.OPC_irem: - case Opcodes.OPC_lrem: - case Opcodes.OPC_frem: - case Opcodes.OPC_drem: - case Opcodes.OPC_ishl: - case Opcodes.OPC_lshl: - case Opcodes.OPC_ishr: - case Opcodes.OPC_lshr: - case Opcodes.OPC_iushr: - case Opcodes.OPC_lushr: - case Opcodes.OPC_iand: - case Opcodes.OPC_land: - case Opcodes.OPC_ior: - case Opcodes.OPC_lor: - case Opcodes.OPC_ixor: - case Opcodes.OPC_lxor: - frame.numberOfStackItems--; - pc++; - break; - case Opcodes.OPC_ineg: - case Opcodes.OPC_lneg: - case Opcodes.OPC_fneg: - case Opcodes.OPC_dneg: - pc++; - break; - case Opcodes.OPC_iinc: - pc += 3; - break; - case Opcodes.OPC_i2l: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.LONG); - pc++; - break; - case Opcodes.OPC_i2f: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.FLOAT); - pc++; - break; - case Opcodes.OPC_i2d: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.DOUBLE); - pc++; - break; - case Opcodes.OPC_l2i: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT); - pc++; - break; - case Opcodes.OPC_l2f: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.FLOAT); - pc++; - break; - case Opcodes.OPC_l2d: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.DOUBLE); - pc++; - break; - case Opcodes.OPC_f2i: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT); - pc++; - break; - case Opcodes.OPC_f2l: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.LONG); - pc++; - break; - case Opcodes.OPC_f2d: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.DOUBLE); - pc++; - break; - case Opcodes.OPC_d2i: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT); - pc++; - break; - case Opcodes.OPC_d2l: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.LONG); - pc++; - break; - case Opcodes.OPC_d2f: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.FLOAT); - pc++; - break; - case Opcodes.OPC_i2b: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.BYTE); - pc++; - break; - case Opcodes.OPC_i2c: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.CHAR); - pc++; - break; - case Opcodes.OPC_i2s: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.SHORT); - pc++; - break; - case Opcodes.OPC_lcmp: - case Opcodes.OPC_fcmpl: - case Opcodes.OPC_fcmpg: - case Opcodes.OPC_dcmpl: - case Opcodes.OPC_dcmpg: - frame.numberOfStackItems-=2; - frame.addStackItem(TypeBinding.INT); - pc++; - break; - case Opcodes.OPC_ifeq: - case Opcodes.OPC_ifne: - case Opcodes.OPC_iflt: - case Opcodes.OPC_ifge: - case Opcodes.OPC_ifgt: - case Opcodes.OPC_ifle: - frame.numberOfStackItems--; - addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc)); - pc += 3; - break; - case Opcodes.OPC_if_icmpeq: - case Opcodes.OPC_if_icmpne: - case Opcodes.OPC_if_icmplt: - case Opcodes.OPC_if_icmpge: - case Opcodes.OPC_if_icmpgt: - case Opcodes.OPC_if_icmple: - case Opcodes.OPC_if_acmpeq: - case Opcodes.OPC_if_acmpne: - frame.numberOfStackItems -= 2; - addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc)); - pc += 3; - break; - case Opcodes.OPC_goto: - addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc)); - pc += 3; - addRealJumpTarget(realJumpTarget, pc - codeOffset); - break; - case Opcodes.OPC_tableswitch: - pc++; - while (((pc - codeOffset) & 0x03) != 0) { - pc++; - } - // default offset - addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc)); - pc += 4; // default - int low = i4At(bytecodes, 0, pc); - pc += 4; - int high = i4At(bytecodes, 0, pc); - pc += 4; - int length = high - low + 1; - for (int i = 0; i < length; i++) { - // pair offset - addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc)); - pc += 4; - } - frame.numberOfStackItems--; - break; - case Opcodes.OPC_lookupswitch: - pc++; - while (((pc - codeOffset) & 0x03) != 0) { - pc++; - } - addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc)); - pc += 4; // default offset - int npairs = (int) u4At(bytecodes, 0, pc); - pc += 4; // npair value - for (int i = 0; i < npairs; i++) { - pc += 4; // case value - // pair offset - addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 0, pc)); - pc += 4; - } - frame.numberOfStackItems--; - break; - case Opcodes.OPC_ireturn: - case Opcodes.OPC_lreturn: - case Opcodes.OPC_freturn: - case Opcodes.OPC_dreturn: - case Opcodes.OPC_areturn: - frame.numberOfStackItems--; - pc++; - addRealJumpTarget(realJumpTarget, pc - codeOffset); - break; - case Opcodes.OPC_return: - pc++; - addRealJumpTarget(realJumpTarget, pc - codeOffset); - break; - case Opcodes.OPC_getstatic: - index = u2At(bytecodes, 1, pc); - int nameAndTypeIndex = u2At(poolContents, 3, - constantPoolOffsets[index]); - int utf8index = u2At(poolContents, 3, - constantPoolOffsets[nameAndTypeIndex]); - char[] descriptor = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - if (descriptor.length == 1) { - // base type - switch(descriptor[0]) { - case 'Z': - frame.addStackItem(TypeBinding.BOOLEAN); - break; - case 'B': - frame.addStackItem(TypeBinding.BYTE); - break; - case 'C': - frame.addStackItem(TypeBinding.CHAR); - break; - case 'D': - frame.addStackItem(TypeBinding.DOUBLE); - break; - case 'F': - frame.addStackItem(TypeBinding.FLOAT); - break; - case 'I': - frame.addStackItem(TypeBinding.INT); - break; - case 'J': - frame.addStackItem(TypeBinding.LONG); - break; - case 'S': - frame.addStackItem(TypeBinding.SHORT); - break; - } - } else if (descriptor[0] == '[') { - frame.addStackItem(new VerificationTypeInfo(0, descriptor)); - } else { - frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(descriptor, 1, descriptor.length - 1))); - } - pc += 3; - break; - case Opcodes.OPC_putstatic: - frame.numberOfStackItems--; - pc += 3; - break; - case Opcodes.OPC_getfield: - index = u2At(bytecodes, 1, pc); - nameAndTypeIndex = u2At(poolContents, 3, - constantPoolOffsets[index]); - utf8index = u2At(poolContents, 3, - constantPoolOffsets[nameAndTypeIndex]); - descriptor = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - frame.numberOfStackItems--; - if (descriptor.length == 1) { - // base type - switch(descriptor[0]) { - case 'Z': - frame.addStackItem(TypeBinding.BOOLEAN); - break; - case 'B': - frame.addStackItem(TypeBinding.BYTE); - break; - case 'C': - frame.addStackItem(TypeBinding.CHAR); - break; - case 'D': - frame.addStackItem(TypeBinding.DOUBLE); - break; - case 'F': - frame.addStackItem(TypeBinding.FLOAT); - break; - case 'I': - frame.addStackItem(TypeBinding.INT); - break; - case 'J': - frame.addStackItem(TypeBinding.LONG); - break; - case 'S': - frame.addStackItem(TypeBinding.SHORT); - break; - } - } else if (descriptor[0] == '[') { - frame.addStackItem(new VerificationTypeInfo(0, descriptor)); - } else { - frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(descriptor, 1, descriptor.length - 1))); - } - pc += 3; - break; - case Opcodes.OPC_putfield: - frame.numberOfStackItems -= 2; - pc += 3; - break; - case Opcodes.OPC_invokevirtual: - index = u2At(bytecodes, 1, pc); - nameAndTypeIndex = u2At(poolContents, 3, - constantPoolOffsets[index]); - utf8index = u2At(poolContents, 3, - constantPoolOffsets[nameAndTypeIndex]); - descriptor = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - utf8index = u2At(poolContents, 1, - constantPoolOffsets[nameAndTypeIndex]); - char[] name = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - frame.numberOfStackItems -= (getParametersCount(descriptor) + 1); - char[] returnType = getReturnType(descriptor); - if (returnType.length == 1) { - // base type - switch(returnType[0]) { - case 'Z': - frame.addStackItem(TypeBinding.BOOLEAN); - break; - case 'B': - frame.addStackItem(TypeBinding.BYTE); - break; - case 'C': - frame.addStackItem(TypeBinding.CHAR); - break; - case 'D': - frame.addStackItem(TypeBinding.DOUBLE); - break; - case 'F': - frame.addStackItem(TypeBinding.FLOAT); - break; - case 'I': - frame.addStackItem(TypeBinding.INT); - break; - case 'J': - frame.addStackItem(TypeBinding.LONG); - break; - case 'S': - frame.addStackItem(TypeBinding.SHORT); - break; - } - } else { - if (returnType[0] == '[') { - frame.addStackItem(new VerificationTypeInfo(0, returnType)); - } else { - frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1))); - } - } - pc += 3; - break; - case Opcodes.OPC_invokedynamic: - index = u2At(bytecodes, 1, pc); - nameAndTypeIndex = u2At(poolContents, 3, - constantPoolOffsets[index]); - utf8index = u2At(poolContents, 3, - constantPoolOffsets[nameAndTypeIndex]); - descriptor = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - frame.numberOfStackItems -= getParametersCount(descriptor); - returnType = getReturnType(descriptor); - if (returnType.length == 1) { - // base type - switch(returnType[0]) { - case 'Z': - frame.addStackItem(TypeBinding.BOOLEAN); - break; - case 'B': - frame.addStackItem(TypeBinding.BYTE); - break; - case 'C': - frame.addStackItem(TypeBinding.CHAR); - break; - case 'D': - frame.addStackItem(TypeBinding.DOUBLE); - break; - case 'F': - frame.addStackItem(TypeBinding.FLOAT); - break; - case 'I': - frame.addStackItem(TypeBinding.INT); - break; - case 'J': - frame.addStackItem(TypeBinding.LONG); - break; - case 'S': - frame.addStackItem(TypeBinding.SHORT); - break; - } - } else { - if (returnType[0] == '[') { - frame.addStackItem(new VerificationTypeInfo(0, returnType)); - } else { - frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1))); - } - } - pc += 5; - break; - case Opcodes.OPC_invokespecial: - index = u2At(bytecodes, 1, pc); - nameAndTypeIndex = u2At(poolContents, 3, - constantPoolOffsets[index]); - utf8index = u2At(poolContents, 3, - constantPoolOffsets[nameAndTypeIndex]); - descriptor = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - utf8index = u2At(poolContents, 1, - constantPoolOffsets[nameAndTypeIndex]); - name = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - frame.numberOfStackItems -= getParametersCount(descriptor); - if (CharOperation.equals(ConstantPool.Init, name)) { - // constructor - frame.stackItems[frame.numberOfStackItems - 1].tag = VerificationTypeInfo.ITEM_OBJECT; - } - frame.numberOfStackItems--; - returnType = getReturnType(descriptor); - if (returnType.length == 1) { - // base type - switch(returnType[0]) { - case 'Z': - frame.addStackItem(TypeBinding.BOOLEAN); - break; - case 'B': - frame.addStackItem(TypeBinding.BYTE); - break; - case 'C': - frame.addStackItem(TypeBinding.CHAR); - break; - case 'D': - frame.addStackItem(TypeBinding.DOUBLE); - break; - case 'F': - frame.addStackItem(TypeBinding.FLOAT); - break; - case 'I': - frame.addStackItem(TypeBinding.INT); - break; - case 'J': - frame.addStackItem(TypeBinding.LONG); - break; - case 'S': - frame.addStackItem(TypeBinding.SHORT); - break; - } - } else { - if (returnType[0] == '[') { - frame.addStackItem(new VerificationTypeInfo(0, returnType)); - } else { - frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1))); - } - } - pc += 3; - break; - case Opcodes.OPC_invokestatic: - index = u2At(bytecodes, 1, pc); - nameAndTypeIndex = u2At(poolContents, 3, - constantPoolOffsets[index]); - utf8index = u2At(poolContents, 3, - constantPoolOffsets[nameAndTypeIndex]); - descriptor = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - utf8index = u2At(poolContents, 1, - constantPoolOffsets[nameAndTypeIndex]); - name = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - frame.numberOfStackItems -= getParametersCount(descriptor); - returnType = getReturnType(descriptor); - if (returnType.length == 1) { - // base type - switch(returnType[0]) { - case 'Z': - frame.addStackItem(TypeBinding.BOOLEAN); - break; - case 'B': - frame.addStackItem(TypeBinding.BYTE); - break; - case 'C': - frame.addStackItem(TypeBinding.CHAR); - break; - case 'D': - frame.addStackItem(TypeBinding.DOUBLE); - break; - case 'F': - frame.addStackItem(TypeBinding.FLOAT); - break; - case 'I': - frame.addStackItem(TypeBinding.INT); - break; - case 'J': - frame.addStackItem(TypeBinding.LONG); - break; - case 'S': - frame.addStackItem(TypeBinding.SHORT); - break; - } - } else { - if (returnType[0] == '[') { - frame.addStackItem(new VerificationTypeInfo(0, returnType)); - } else { - frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1))); - } - } - pc += 3; - break; - case Opcodes.OPC_invokeinterface: - index = u2At(bytecodes, 1, pc); - nameAndTypeIndex = u2At(poolContents, 3, - constantPoolOffsets[index]); - utf8index = u2At(poolContents, 3, - constantPoolOffsets[nameAndTypeIndex]); - descriptor = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - utf8index = u2At(poolContents, 1, - constantPoolOffsets[nameAndTypeIndex]); - name = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - // we don't need count and args - // u1At(bytecodes, 3, pc); // count - // u1At(bytecodes, 4, pc); // extra args - frame.numberOfStackItems -= (getParametersCount(descriptor) + 1); - returnType = getReturnType(descriptor); - if (returnType.length == 1) { - // base type - switch(returnType[0]) { - case 'Z': - frame.addStackItem(TypeBinding.BOOLEAN); - break; - case 'B': - frame.addStackItem(TypeBinding.BYTE); - break; - case 'C': - frame.addStackItem(TypeBinding.CHAR); - break; - case 'D': - frame.addStackItem(TypeBinding.DOUBLE); - break; - case 'F': - frame.addStackItem(TypeBinding.FLOAT); - break; - case 'I': - frame.addStackItem(TypeBinding.INT); - break; - case 'J': - frame.addStackItem(TypeBinding.LONG); - break; - case 'S': - frame.addStackItem(TypeBinding.SHORT); - break; - } - } else { - if (returnType[0] == '[') { - frame.addStackItem(new VerificationTypeInfo(0, returnType)); - } else { - frame.addStackItem(new VerificationTypeInfo(0, CharOperation.subarray(returnType, 1, returnType.length - 1))); - } - } - pc += 5; - break; - case Opcodes.OPC_new: - index = u2At(bytecodes, 1, pc); - utf8index = u2At(poolContents, 1, - constantPoolOffsets[index]); - char[] className = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - VerificationTypeInfo verificationTypeInfo = new VerificationTypeInfo(0, VerificationTypeInfo.ITEM_UNINITIALIZED, className); - verificationTypeInfo.offset = currentPC; - frame.addStackItem(verificationTypeInfo); - pc += 3; - break; - case Opcodes.OPC_newarray: - char[] constantPoolName = null; - switch (u1At(bytecodes, 1, pc)) { - case ClassFileConstants.INT_ARRAY : - constantPoolName = new char[] { '[', 'I' }; - break; - case ClassFileConstants.BYTE_ARRAY : - constantPoolName = new char[] { '[', 'B' }; - break; - case ClassFileConstants.BOOLEAN_ARRAY : - constantPoolName = new char[] { '[', 'Z' }; - break; - case ClassFileConstants.SHORT_ARRAY : - constantPoolName = new char[] { '[', 'S' }; - break; - case ClassFileConstants.CHAR_ARRAY : - constantPoolName = new char[] { '[', 'C' }; - break; - case ClassFileConstants.LONG_ARRAY : - constantPoolName = new char[] { '[', 'J' }; - break; - case ClassFileConstants.FLOAT_ARRAY : - constantPoolName = new char[] { '[', 'F' }; - break; - case ClassFileConstants.DOUBLE_ARRAY : - constantPoolName = new char[] { '[', 'D' }; - break; - } - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeIds.T_JavaLangObject, constantPoolName); - pc += 2; - break; - case Opcodes.OPC_anewarray: - index = u2At(bytecodes, 1, pc); - utf8index = u2At(poolContents, 1, - constantPoolOffsets[index]); - className = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - int classNameLength = className.length; - if (className[0] != '[') { - // this is a type name (class or interface). So we add appropriate '[', 'L' and ';'. - System.arraycopy(className, 0, (constantPoolName = new char[classNameLength + 3]), 2, classNameLength); - constantPoolName[0] = '['; - constantPoolName[1] = 'L'; - constantPoolName[classNameLength + 2] = ';'; - } else { - // if class name is already an array, we just need to add one dimension - System.arraycopy(className, 0, (constantPoolName = new char[classNameLength + 1]), 1, classNameLength); - constantPoolName[0] = '['; - } - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(0, constantPoolName); - pc += 3; - break; - case Opcodes.OPC_arraylength: - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT); - pc++; - break; - case Opcodes.OPC_athrow: - frame.numberOfStackItems--; - pc++; - addRealJumpTarget(realJumpTarget, pc - codeOffset); - break; - case Opcodes.OPC_checkcast: - index = u2At(bytecodes, 1, pc); - utf8index = u2At(poolContents, 1, - constantPoolOffsets[index]); - className = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(0, className); - pc += 3; - break; - case Opcodes.OPC_instanceof: - // no need to know the class index = u2At(bytecodes, 1, pc); - frame.stackItems[frame.numberOfStackItems - 1] = new VerificationTypeInfo(TypeBinding.INT); - pc += 3; - break; - case Opcodes.OPC_monitorenter: - case Opcodes.OPC_monitorexit: - frame.numberOfStackItems--; - pc++; - break; - case Opcodes.OPC_wide: - opcode = (byte) u1At(bytecodes, 1, pc); - if (opcode == Opcodes.OPC_iinc) { - // index = u2At(bytecodes, 2, pc); - // i2At(bytecodes, 4, pc); // const - // we don't need the index and the const value - pc += 6; - } else { - index = u2At(bytecodes, 2, pc); - // need to handle iload, fload, aload, lload, dload, istore, fstore, astore, lstore or dstore - switch(opcode) { - case Opcodes.OPC_iload : - frame.addStackItem(TypeBinding.INT); - break; - case Opcodes.OPC_fload : - frame.addStackItem(TypeBinding.FLOAT); - break; - case Opcodes.OPC_aload : - localsN = frame.locals[index]; - if (localsN == null) { - localsN = retrieveLocal(currentPC, index); - } - frame.addStackItem(localsN); - break; - case Opcodes.OPC_lload : - frame.addStackItem(TypeBinding.LONG); - break; - case Opcodes.OPC_dload : - frame.addStackItem(TypeBinding.DOUBLE); - break; - case Opcodes.OPC_istore : - frame.numberOfStackItems--; - break; - case Opcodes.OPC_fstore : - frame.numberOfStackItems--; - break; - case Opcodes.OPC_astore : - frame.locals[index] = frame.stackItems[frame.numberOfStackItems - 1]; - frame.numberOfStackItems--; - break; - case Opcodes.OPC_lstore : - frame.numberOfStackItems--; - break; - case Opcodes.OPC_dstore : - frame.numberOfStackItems--; - break; - } - pc += 4; - } - break; - case Opcodes.OPC_multianewarray: - index = u2At(bytecodes, 1, pc); - utf8index = u2At(poolContents, 1, - constantPoolOffsets[index]); - className = utf8At(poolContents, - constantPoolOffsets[utf8index] + 3, u2At( - poolContents, 1, - constantPoolOffsets[utf8index])); - int dimensions = u1At(bytecodes, 3, pc); // dimensions - frame.numberOfStackItems -= dimensions; - classNameLength = className.length; - constantPoolName = new char[classNameLength + dimensions]; - for (int i = 0; i < dimensions; i++) { - constantPoolName[i] = '['; - } - System.arraycopy(className, 0, constantPoolName, dimensions, classNameLength); - frame.addStackItem(new VerificationTypeInfo(0, constantPoolName)); - pc += 4; - break; - case Opcodes.OPC_ifnull: - case Opcodes.OPC_ifnonnull: - frame.numberOfStackItems--; - addRealJumpTarget(realJumpTarget, currentPC + i2At(bytecodes, 1, pc)); - pc += 3; - break; - case Opcodes.OPC_goto_w: - addRealJumpTarget(realJumpTarget, currentPC + i4At(bytecodes, 1, pc)); - pc += 5; - addRealJumpTarget(realJumpTarget, pc - codeOffset); // handle infinite loop - break; - default: // should not occur - if (this.codeStream.methodDeclaration != null) { - this.codeStream.methodDeclaration.scope.problemReporter().abortDueToInternalError( - Messages.bind( - Messages.abort_invalidOpcode, - new Object[] { - new Byte(opcode), - new Integer(pc), - new String(methodBinding.shortReadableName()), - }), - this.codeStream.methodDeclaration); - } else { - this.codeStream.lambdaExpression.scope.problemReporter().abortDueToInternalError( - Messages.bind( - Messages.abort_invalidOpcode, - new Object[] { - new Byte(opcode), - new Integer(pc), - new String(methodBinding.shortReadableName()), - }), - this.codeStream.lambdaExpression); - } - break; - } - if (pc >= (codeLength + codeOffset)) { - break; - } - } - return filterFakeFrames(realJumpTarget, frames, codeLength); - } - - private void addRealJumpTarget(Set realJumpTarget, int pc) { - realJumpTarget.add(new Integer(pc)); - } - private void add(Map frames, StackMapFrame frame) { - frames.put(new Integer(frame.pc), frame); - } - private final int u1At(byte[] reference, int relativeOffset, - int structOffset) { - return (reference[relativeOffset + structOffset] & 0xFF); - } - - private final int u2At(byte[] reference, int relativeOffset, - int structOffset) { - int position = relativeOffset + structOffset; - return ((reference[position++] & 0xFF) << 8) - + (reference[position] & 0xFF); - } - - private final long u4At(byte[] reference, int relativeOffset, - int structOffset) { - int position = relativeOffset + structOffset; - return (((reference[position++] & 0xFFL) << 24) - + ((reference[position++] & 0xFF) << 16) - + ((reference[position++] & 0xFF) << 8) + (reference[position] & 0xFF)); - } - // AspectJ Extension - void writeToContents(byte[] data) { - int N = data.length; - if (contentsOffset + N >= this.contents.length) { - resizeContents(N); - } - System.arraycopy(data,0,contents,contentsOffset,N); - contentsOffset += N; - } - // End AspectJ Extension - - private final int i2At(byte[] reference, int relativeOffset, int structOffset) { - int position = relativeOffset + structOffset; - return (reference[position++] << 8) + (reference[position] & 0xFF); - } - - public char[] utf8At(byte[] reference, int absoluteOffset, - int bytesAvailable) { - int length = bytesAvailable; - char outputBuf[] = new char[bytesAvailable]; - int outputPos = 0; - int readOffset = absoluteOffset; - - while (length != 0) { - int x = reference[readOffset++] & 0xFF; - length--; - if ((0x80 & x) != 0) { - if ((x & 0x20) != 0) { - length -= 2; - x = ((x & 0xF) << 12) - | ((reference[readOffset++] & 0x3F) << 6) - | (reference[readOffset++] & 0x3F); - } else { - length--; - x = ((x & 0x1F) << 6) | (reference[readOffset++] & 0x3F); - } - } - outputBuf[outputPos++] = (char) x; - } - - if (outputPos != bytesAvailable) { - System.arraycopy(outputBuf, 0, (outputBuf = new char[outputPos]), - 0, outputPos); - } - return outputBuf; - } -} |