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;
this.resolve(classScope);
codeStream.reset(this, classFile);
TypeDeclaration declaringType = classScope.referenceContext;
// initialize local positions - including initializer scope.
MethodScope staticInitializerScope = declaringType.staticInitializerScope;
staticInitializerScope.computeLocalVariablePositions(0, codeStream);
// 1.4 feature
// This has to be done before any other initialization
// AspectJ Extension - move logic to helper method
// was:
//if (this.assertionSyntheticFieldBinding != null) {
// // generate code related to the activation of assertion for this class
// codeStream.generateClassLiteralAccessForType(
// 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.putstatic(this.assertionSyntheticFieldBinding);
//}
generateSyntheticCode(classScope, codeStream);
// End AspectJ Extension
// generate static fields/initializers/enum constants
final FieldDeclaration[] fieldDeclarations = declaringType.fields;
BlockScope lastInitializerScope = null;
if (TypeDeclaration.kind(declaringType.modifiers) == TypeDeclaration.ENUM_DECL) {
int enumCount = 0;
int remainingFieldCount = 0;
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);
enumCount++;
} 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.getstatic(fieldDecl.binding);
codeStream.aastore();
}
}
}
}
codeStream.putstatic(declaringType.enumValuesSyntheticfield);
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; i++) {
FieldDeclaration fieldDecl = fieldDeclarations[i];
switch (fieldDecl.getKind()) {
case AbstractVariableDeclaration.ENUM_CONSTANT :
break;
case AbstractVariableDeclaration.INITIALIZER :
if (!fieldDecl.isStatic())
break;
lastInitializerScope = ((Initializer) fieldDecl).block.scope;
fieldDecl.generateCode(staticInitializerScope, codeStream);
break;
case AbstractVariableDeclaration.FIELD :
if (!fieldDecl.binding.isStatic())
break;
lastInitializerScope = null;
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;
lastInitializerScope = ((Initializer) fieldDecl).block.scope;
fieldDecl.generateCode(staticInitializerScope, codeStream);
break;
case AbstractVariableDeclaration.FIELD :
if (!fieldDecl.binding.isStatic())
break;
lastInitializerScope = null;
fieldDecl.generateCode(staticInitializerScope, codeStream);
break;
}
}
}
}
// AspectJ Extension
generatePostSyntheticCode(classScope, codeStream);
// End AspectJ Extension
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 (lastInitializerScope != null) {