Search in sources :

Example 1 with CodeStream

use of org.eclipse.jdt.internal.compiler.codegen.CodeStream in project bazel-jdt-java-toolchain by salesforce.

the class Clinit method generateCode.

/**
 * Bytecode generation for a <clinit> method
 *
 * @param classScope org.eclipse.jdt.internal.compiler.lookup.ClassScope
 * @param classFile org.eclipse.jdt.internal.compiler.codegen.ClassFile
 */
private void generateCode(ClassScope classScope, ClassFile classFile, int clinitOffset) {
    ConstantPool constantPool = classFile.constantPool;
    int constantPoolOffset = constantPool.currentOffset;
    int constantPoolIndex = constantPool.currentIndex;
    classFile.generateMethodInfoHeaderForClinit();
    int codeAttributeOffset = classFile.contentsOffset;
    classFile.generateCodeAttributeHeader();
    CodeStream codeStream = classFile.codeStream;
    resolve(classScope);
    codeStream.reset(this, classFile);
    TypeDeclaration declaringType = classScope.referenceContext;
    // initialize local positions - including initializer scope.
    MethodScope staticInitializerScope = declaringType.staticInitializerScope;
    staticInitializerScope.computeLocalVariablePositions(0, codeStream);
    // This has to be done before any other initialization
    if (this.assertionSyntheticFieldBinding != null) {
        // generate code related to the activation of assertion for this class
        codeStream.generateClassLiteralAccessForType(classScope, classScope.outerMostClassScope().enclosingSourceType(), this.classLiteralSyntheticField);
        codeStream.invokeJavaLangClassDesiredAssertionStatus();
        BranchLabel falseLabel = new BranchLabel(codeStream);
        codeStream.ifne(falseLabel);
        codeStream.iconst_1();
        BranchLabel jumpLabel = new BranchLabel(codeStream);
        codeStream.decrStackSize(1);
        codeStream.goto_(jumpLabel);
        falseLabel.place();
        codeStream.iconst_0();
        jumpLabel.place();
        codeStream.fieldAccess(Opcodes.OPC_putstatic, this.assertionSyntheticFieldBinding, null);
    }
    boolean isJava9 = classScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK9;
    // generate static fields/initializers/enum constants
    final FieldDeclaration[] fieldDeclarations = declaringType.fields;
    int sourcePosition = -1;
    int remainingFieldCount = 0;
    if (TypeDeclaration.kind(declaringType.modifiers) == TypeDeclaration.ENUM_DECL) {
        int enumCount = declaringType.enumConstantsCounter;
        if (!isJava9 && enumCount > ENUM_CONSTANTS_THRESHOLD) {
            // generate synthetic methods to initialize all the enum constants
            int begin = -1;
            int count = 0;
            if (fieldDeclarations != null) {
                int max = fieldDeclarations.length;
                for (int i = 0; i < max; i++) {
                    FieldDeclaration fieldDecl = fieldDeclarations[i];
                    if (fieldDecl.isStatic()) {
                        if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
                            if (begin == -1) {
                                begin = i;
                            }
                            count++;
                            if (count > ENUM_CONSTANTS_THRESHOLD) {
                                SyntheticMethodBinding syntheticMethod = declaringType.binding.addSyntheticMethodForEnumInitialization(begin, i);
                                codeStream.invoke(Opcodes.OPC_invokestatic, syntheticMethod, null);
                                begin = i;
                                count = 1;
                            }
                        } else {
                            remainingFieldCount++;
                        }
                    }
                }
                if (count != 0) {
                    // add last synthetic method
                    SyntheticMethodBinding syntheticMethod = declaringType.binding.addSyntheticMethodForEnumInitialization(begin, max);
                    codeStream.invoke(Opcodes.OPC_invokestatic, syntheticMethod, null);
                }
            }
        } else if (fieldDeclarations != null) {
            for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
                FieldDeclaration fieldDecl = fieldDeclarations[i];
                if (fieldDecl.isStatic()) {
                    if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
                        fieldDecl.generateCode(staticInitializerScope, codeStream);
                    } else {
                        remainingFieldCount++;
                    }
                }
            }
        }
        // enum need to initialize $VALUES synthetic cache of enum constants
        // $VALUES := new <EnumType>[<enumCount>]
        codeStream.generateInlinedValue(enumCount);
        codeStream.anewarray(declaringType.binding);
        if (enumCount > 0) {
            if (fieldDeclarations != null) {
                for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
                    FieldDeclaration fieldDecl = fieldDeclarations[i];
                    // $VALUES[i] = <enum-constant-i>
                    if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) {
                        codeStream.dup();
                        codeStream.generateInlinedValue(fieldDecl.binding.id);
                        codeStream.fieldAccess(Opcodes.OPC_getstatic, fieldDecl.binding, null);
                        codeStream.aastore();
                    }
                }
            }
        }
        codeStream.fieldAccess(Opcodes.OPC_putstatic, declaringType.enumValuesSyntheticfield, null);
        if (remainingFieldCount != 0) {
            // if fields that are not enum constants need to be generated (static initializer/static field)
            for (int i = 0, max = fieldDeclarations.length; i < max && remainingFieldCount >= 0; i++) {
                FieldDeclaration fieldDecl = fieldDeclarations[i];
                switch(fieldDecl.getKind()) {
                    case AbstractVariableDeclaration.ENUM_CONSTANT:
                        break;
                    case AbstractVariableDeclaration.INITIALIZER:
                        if (!fieldDecl.isStatic()) {
                            break;
                        }
                        remainingFieldCount--;
                        sourcePosition = ((Initializer) fieldDecl).block.sourceEnd;
                        fieldDecl.generateCode(staticInitializerScope, codeStream);
                        break;
                    case AbstractVariableDeclaration.FIELD:
                        if (!fieldDecl.binding.isStatic()) {
                            break;
                        }
                        remainingFieldCount--;
                        sourcePosition = fieldDecl.declarationEnd;
                        fieldDecl.generateCode(staticInitializerScope, codeStream);
                        break;
                }
            }
        }
    } else {
        if (fieldDeclarations != null) {
            for (int i = 0, max = fieldDeclarations.length; i < max; i++) {
                FieldDeclaration fieldDecl = fieldDeclarations[i];
                switch(fieldDecl.getKind()) {
                    case AbstractVariableDeclaration.INITIALIZER:
                        if (!fieldDecl.isStatic())
                            break;
                        sourcePosition = ((Initializer) fieldDecl).block.sourceEnd;
                        fieldDecl.generateCode(staticInitializerScope, codeStream);
                        break;
                    case AbstractVariableDeclaration.FIELD:
                        if (!fieldDecl.binding.isStatic())
                            break;
                        sourcePosition = fieldDecl.declarationEnd;
                        fieldDecl.generateCode(staticInitializerScope, codeStream);
                        break;
                }
            }
        }
        if (isJava9) {
            declaringType.binding.generateSyntheticFinalFieldInitialization(codeStream);
        }
    }
    if (codeStream.position == 0) {
        // do not need to output a Clinit if no bytecodes
        // so we reset the offset inside the byte array contents.
        classFile.contentsOffset = clinitOffset;
        // like we don't addd a method we need to undo the increment on the method count
        classFile.methodCount--;
        // reset the constant pool to its state before the clinit
        constantPool.resetForClinit(constantPoolIndex, constantPoolOffset);
    } else {
        if ((this.bits & ASTNode.NeedFreeReturn) != 0) {
            int before = codeStream.position;
            codeStream.return_();
            if (sourcePosition != -1) {
                // expand the last initializer variables to include the trailing return
                codeStream.recordPositionsFrom(before, sourcePosition);
            }
        }
        // Record the end of the clinit: point to the declaration of the class
        codeStream.recordPositionsFrom(0, declaringType.sourceStart);
        classFile.completeCodeAttributeForClinit(codeAttributeOffset, classScope);
    }
}
Also used : CodeStream(org.eclipse.jdt.internal.compiler.codegen.CodeStream) BranchLabel(org.eclipse.jdt.internal.compiler.codegen.BranchLabel) ConstantPool(org.eclipse.jdt.internal.compiler.codegen.ConstantPool) SyntheticMethodBinding(org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding) MethodScope(org.eclipse.jdt.internal.compiler.lookup.MethodScope)

Example 2 with CodeStream

use of org.eclipse.jdt.internal.compiler.codegen.CodeStream in project bazel-jdt-java-toolchain by salesforce.

the class LambdaExpression method generateCode.

public void generateCode(ClassFile classFile) {
    classFile.generateMethodInfoHeader(this.binding);
    int methodAttributeOffset = classFile.contentsOffset;
    int attributeNumber = classFile.generateMethodInfoAttributes(this.binding);
    int codeAttributeOffset = classFile.contentsOffset;
    classFile.generateCodeAttributeHeader();
    CodeStream codeStream = classFile.codeStream;
    codeStream.reset(this, classFile);
    // initialize local positions
    this.scope.computeLocalVariablePositions(this.outerLocalVariablesSlotSize + (this.binding.isStatic() ? 0 : 1), codeStream);
    if (this.outerLocalVariables != null) {
        for (int i = 0, max = this.outerLocalVariables.length; i < max; i++) {
            LocalVariableBinding argBinding;
            codeStream.addVisibleLocalVariable(argBinding = this.outerLocalVariables[i]);
            codeStream.record(argBinding);
            argBinding.recordInitializationStartPC(0);
        }
    }
    // arguments initialization for local variable debug attributes
    if (this.arguments != null) {
        for (int i = 0, max = this.arguments.length; i < max; i++) {
            LocalVariableBinding argBinding;
            codeStream.addVisibleLocalVariable(argBinding = this.arguments[i].binding);
            argBinding.recordInitializationStartPC(0);
        }
    }
    if (this.body instanceof Block) {
        this.body.generateCode(this.scope, codeStream);
        if ((this.bits & ASTNode.NeedFreeReturn) != 0) {
            codeStream.return_();
        }
    } else {
        Expression expression = (Expression) this.body;
        expression.generateCode(this.scope, codeStream, true);
        if (this.binding.returnType == TypeBinding.VOID) {
            codeStream.return_();
        } else {
            codeStream.generateReturnBytecode(expression);
        }
    }
    // local variable attributes
    codeStream.exitUserScope(this.scope);
    // WAS declarationSourceEnd.
    codeStream.recordPositionsFrom(0, this.sourceEnd);
    try {
        classFile.completeCodeAttribute(codeAttributeOffset, this.scope);
    } catch (NegativeArraySizeException e) {
        throw new AbortMethod(this.scope.referenceCompilationUnit().compilationResult, null);
    }
    attributeNumber++;
    classFile.completeMethodInfo(this.binding, methodAttributeOffset, attributeNumber);
}
Also used : CodeStream(org.eclipse.jdt.internal.compiler.codegen.CodeStream) LocalVariableBinding(org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding) AbortMethod(org.eclipse.jdt.internal.compiler.problem.AbortMethod)

Aggregations

CodeStream (org.eclipse.jdt.internal.compiler.codegen.CodeStream)2 BranchLabel (org.eclipse.jdt.internal.compiler.codegen.BranchLabel)1 ConstantPool (org.eclipse.jdt.internal.compiler.codegen.ConstantPool)1 LocalVariableBinding (org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding)1 MethodScope (org.eclipse.jdt.internal.compiler.lookup.MethodScope)1 SyntheticMethodBinding (org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding)1 AbortMethod (org.eclipse.jdt.internal.compiler.problem.AbortMethod)1