Search in sources :

Example 1 with SyntheticMethodBinding

use of org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding 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 SyntheticMethodBinding

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

the class LambdaExpression method getMethodBinding.

// Return the actual method binding devoid of synthetics.
@Override
public MethodBinding getMethodBinding() {
    if (this.actualMethodBinding == null) {
        if (this.binding != null) {
            // Get rid of the synthetic arguments added via addSyntheticArgument()
            TypeBinding[] newParams = null;
            if (this.binding instanceof SyntheticMethodBinding && this.outerLocalVariables.length > 0) {
                newParams = new TypeBinding[this.binding.parameters.length - this.outerLocalVariables.length];
                System.arraycopy(this.binding.parameters, this.outerLocalVariables.length, newParams, 0, newParams.length);
            } else {
                newParams = this.binding.parameters;
            }
            this.actualMethodBinding = new MethodBinding(this.binding.modifiers, this.binding.selector, this.binding.returnType, newParams, this.binding.thrownExceptions, this.binding.declaringClass);
            this.actualMethodBinding.tagBits = this.binding.tagBits;
        } else {
            this.actualMethodBinding = new ProblemMethodBinding(CharOperation.NO_CHAR, null, ProblemReasons.NoSuchSingleAbstractMethod);
        }
    }
    return this.actualMethodBinding;
}
Also used : ProblemMethodBinding(org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding) ParameterizedTypeBinding(org.eclipse.jdt.internal.compiler.lookup.ParameterizedTypeBinding) TypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding) SourceTypeBinding(org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding) PolyTypeBinding(org.eclipse.jdt.internal.compiler.lookup.PolyTypeBinding) LocalTypeBinding(org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding) SyntheticMethodBinding(org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding) MethodBinding(org.eclipse.jdt.internal.compiler.lookup.MethodBinding) SyntheticMethodBinding(org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding) ProblemMethodBinding(org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding) ParameterizedGenericMethodBinding(org.eclipse.jdt.internal.compiler.lookup.ParameterizedGenericMethodBinding)

Example 3 with SyntheticMethodBinding

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

the class LambdaExpression method generateCode.

@Override
public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
    if (this.shouldCaptureInstance) {
        this.binding.modifiers &= ~ClassFileConstants.AccStatic;
    } else {
        this.binding.modifiers |= ClassFileConstants.AccStatic;
    }
    SourceTypeBinding sourceType = currentScope.enclosingSourceType();
    boolean firstSpill = !(this.binding instanceof SyntheticMethodBinding);
    this.binding = sourceType.addSyntheticMethod(this);
    int pc = codeStream.position;
    StringBuilder signature = new StringBuilder();
    signature.append('(');
    if (this.shouldCaptureInstance) {
        codeStream.aload_0();
        signature.append(sourceType.signature());
    }
    for (int i = 0, length = this.outerLocalVariables == null ? 0 : this.outerLocalVariables.length; i < length; i++) {
        SyntheticArgumentBinding syntheticArgument = this.outerLocalVariables[i];
        if (this.shouldCaptureInstance && firstSpill) {
            // finally block handling results in extra spills, avoid side effect.
            syntheticArgument.resolvedPosition++;
        }
        signature.append(syntheticArgument.type.signature());
        LocalVariableBinding capturedOuterLocal = syntheticArgument.actualOuterLocalVariable;
        VariableBinding[] path = currentScope.getEmulationPath(capturedOuterLocal);
        codeStream.generateOuterAccess(path, this, capturedOuterLocal, currentScope);
    }
    signature.append(')');
    if (this.expectedType instanceof IntersectionTypeBinding18) {
        signature.append(((IntersectionTypeBinding18) this.expectedType).getSAMType(currentScope).signature());
    } else {
        signature.append(this.expectedType.signature());
    }
    int invokeDynamicNumber = codeStream.classFile.recordBootstrapMethod(this);
    codeStream.invokeDynamic(invokeDynamicNumber, (this.shouldCaptureInstance ? 1 : 0) + this.outerLocalVariablesSlotSize, 1, this.descriptor.selector, signature.toString().toCharArray(), this.resolvedType.id, this.resolvedType);
    if (!valueRequired)
        codeStream.pop();
    codeStream.recordPositionsFrom(pc, this.sourceStart);
}
Also used : SyntheticArgumentBinding(org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding) SyntheticMethodBinding(org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding) SourceTypeBinding(org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding) LocalVariableBinding(org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding) VariableBinding(org.eclipse.jdt.internal.compiler.lookup.VariableBinding) IntersectionTypeBinding18(org.eclipse.jdt.internal.compiler.lookup.IntersectionTypeBinding18) LocalVariableBinding(org.eclipse.jdt.internal.compiler.lookup.LocalVariableBinding)

Example 4 with SyntheticMethodBinding

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

the class QualifiedNameReference method generateCompoundAssignment.

@Override
public void generateCompoundAssignment(BlockScope currentScope, CodeStream codeStream, Expression expression, int operator, int assignmentImplicitConversion, boolean valueRequired) {
    FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
    // check if compound assignment is the only usage of a private field
    reportOnlyUselesslyReadPrivateField(currentScope, lastFieldBinding, valueRequired);
    boolean isFirst = lastFieldBinding == this.binding && (this.indexOfFirstFieldBinding == 1 || TypeBinding.equalsEquals(lastFieldBinding.declaringClass, currentScope.enclosingReceiverType())) && // could be dup: next.next.next
    this.otherBindings == null;
    TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst);
    SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
    if (lastFieldBinding.isStatic()) {
        if (accessor == null) {
            codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
        } else {
            codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null);
        }
    } else {
        codeStream.dup();
        if (accessor == null) {
            codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, constantPoolDeclaringClass);
        } else {
            codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null);
        }
    }
    // the last field access is a write access
    // perform the actual compound operation
    int operationTypeID;
    switch(operationTypeID = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) {
        case T_JavaLangString:
        case T_JavaLangObject:
        case T_undefined:
            codeStream.generateStringConcatenationAppend(currentScope, null, expression);
            break;
        default:
            TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length);
            if (requiredGenericCast != null)
                codeStream.checkcast(requiredGenericCast);
            // promote the array reference to the suitable operation type
            codeStream.generateImplicitConversion(this.implicitConversion);
            // generate the increment value (will by itself  be promoted to the operation value)
            if (expression == IntLiteral.One) {
                // prefix operation
                codeStream.generateConstant(expression.constant, this.implicitConversion);
            } else {
                expression.generateCode(currentScope, codeStream, true);
            }
            // perform the operation
            codeStream.sendOperator(operator, operationTypeID);
            // cast the value back to the array reference type
            codeStream.generateImplicitConversion(assignmentImplicitConversion);
    }
    // actual assignment
    fieldStore(currentScope, codeStream, lastFieldBinding, this.syntheticWriteAccessor, getFinalReceiverType(), false, /*implicit this*/
    valueRequired);
// equivalent to valuesRequired[maxOtherBindings]
}
Also used : SourceTypeBinding(org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding) TypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding) MissingTypeBinding(org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding) FieldBinding(org.eclipse.jdt.internal.compiler.lookup.FieldBinding) ProblemFieldBinding(org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding) SyntheticMethodBinding(org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding)

Example 5 with SyntheticMethodBinding

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

the class QualifiedNameReference method generatePostIncrement.

@Override
public void generatePostIncrement(BlockScope currentScope, CodeStream codeStream, CompoundAssignment postIncrement, boolean valueRequired) {
    FieldBinding lastFieldBinding = generateReadSequence(currentScope, codeStream);
    // check if this post increment is the only usage of a private field
    reportOnlyUselesslyReadPrivateField(currentScope, lastFieldBinding, valueRequired);
    boolean isFirst = lastFieldBinding == this.binding && (this.indexOfFirstFieldBinding == 1 || TypeBinding.equalsEquals(lastFieldBinding.declaringClass, currentScope.enclosingReceiverType())) && // could be dup: next.next.next
    this.otherBindings == null;
    TypeBinding constantPoolDeclaringClass = CodeStream.getConstantPoolDeclaringClass(currentScope, lastFieldBinding, getFinalReceiverType(), isFirst);
    SyntheticMethodBinding accessor = this.syntheticReadAccessors == null ? null : this.syntheticReadAccessors[this.syntheticReadAccessors.length - 1];
    if (lastFieldBinding.isStatic()) {
        if (accessor == null) {
            codeStream.fieldAccess(Opcodes.OPC_getstatic, lastFieldBinding, constantPoolDeclaringClass);
        } else {
            codeStream.invoke(Opcodes.OPC_invokestatic, accessor, constantPoolDeclaringClass);
        }
    } else {
        codeStream.dup();
        if (accessor == null) {
            codeStream.fieldAccess(Opcodes.OPC_getfield, lastFieldBinding, null);
        } else {
            codeStream.invoke(Opcodes.OPC_invokestatic, accessor, null);
        }
    }
    TypeBinding requiredGenericCast = getGenericCast(this.otherBindings == null ? 0 : this.otherBindings.length);
    TypeBinding operandType;
    if (requiredGenericCast != null) {
        codeStream.checkcast(requiredGenericCast);
        operandType = requiredGenericCast;
    } else {
        operandType = lastFieldBinding.type;
    }
    // duplicate the old field value
    if (valueRequired) {
        if (lastFieldBinding.isStatic()) {
            switch(operandType.id) {
                case TypeIds.T_long:
                case TypeIds.T_double:
                    codeStream.dup2();
                    break;
                default:
                    codeStream.dup();
                    break;
            }
        } else {
            // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
            switch(operandType.id) {
                case TypeIds.T_long:
                case TypeIds.T_double:
                    codeStream.dup2_x1();
                    break;
                default:
                    codeStream.dup_x1();
                    break;
            }
        }
    }
    codeStream.generateImplicitConversion(this.implicitConversion);
    codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
    codeStream.sendOperator(postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
    codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
    fieldStore(currentScope, codeStream, lastFieldBinding, this.syntheticWriteAccessor, getFinalReceiverType(), false, /*implicit this*/
    false);
}
Also used : SourceTypeBinding(org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding) TypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding) MissingTypeBinding(org.eclipse.jdt.internal.compiler.lookup.MissingTypeBinding) FieldBinding(org.eclipse.jdt.internal.compiler.lookup.FieldBinding) ProblemFieldBinding(org.eclipse.jdt.internal.compiler.lookup.ProblemFieldBinding) SyntheticMethodBinding(org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding)

Aggregations

SyntheticMethodBinding (org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding)10 SourceTypeBinding (org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding)8 TypeBinding (org.eclipse.jdt.internal.compiler.lookup.TypeBinding)7 FieldBinding (org.eclipse.jdt.internal.compiler.lookup.FieldBinding)5 LocalTypeBinding (org.eclipse.jdt.internal.compiler.lookup.LocalTypeBinding)4 MethodBinding (org.eclipse.jdt.internal.compiler.lookup.MethodBinding)4 SyntheticArgumentBinding (org.eclipse.jdt.internal.compiler.lookup.SyntheticArgumentBinding)4 AbstractMethodDeclaration (org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration)3 Argument (org.eclipse.jdt.internal.compiler.ast.Argument)3 ArrayList (java.util.ArrayList)2 Arrays (java.util.Arrays)2 Collections (java.util.Collections)2 Comparator (java.util.Comparator)2 HashMap (java.util.HashMap)2 HashSet (java.util.HashSet)2 Iterator (java.util.Iterator)2 List (java.util.List)2 Map (java.util.Map)2 Set (java.util.Set)2 Predicate (java.util.function.Predicate)2