aboutsummaryrefslogtreecommitdiffstats
path: root/org.eclipse.jdt.core
diff options
context:
space:
mode:
authorAndy Clement <aclement@pivotal.io>2018-10-11 10:58:44 -0700
committerAndy Clement <aclement@pivotal.io>2018-10-11 10:58:44 -0700
commitef7411136acfe9dd531d8e9faeb439025cd3c3c6 (patch)
tree2dc44938f6f3c6d6064636d3ff18db7fb4b6351f /org.eclipse.jdt.core
parenta913ec7fb308c794bd53f33f1d5b7163d144cf23 (diff)
downloadaspectj-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.java6784
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;
- }
-}