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);
}
}
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;
}
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);
}
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]
}
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);
}
Aggregations