### Eclipse Workspace Patch 1.0 #P org.eclipse.jdt.core Index: compiler/org/eclipse/jdt/internal/compiler/ClassFile.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ClassFile.java,v retrieving revision 1.203 diff -u -r1.203 ClassFile.java --- compiler/org/eclipse/jdt/internal/compiler/ClassFile.java 27 Oct 2010 02:55:30 -0000 1.203 +++ compiler/org/eclipse/jdt/internal/compiler/ClassFile.java 20 Dec 2010 00:49:12 -0000 @@ -823,6 +823,9 @@ case SyntheticMethodBinding.SwitchTable : // generate a method info to define the switch table synthetic method addSyntheticSwitchTable(syntheticMethod); + break; + case SyntheticMethodBinding.TooManyEnumsConstants : + addSyntheticEnumInitializationMethod(syntheticMethod); } } } @@ -918,6 +921,29 @@ 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 Index: compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java,v retrieving revision 1.61 diff -u -r1.61 Clinit.java --- compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java 9 Nov 2010 19:59:19 -0000 1.61 +++ compiler/org/eclipse/jdt/internal/compiler/ast/Clinit.java 20 Dec 2010 00:49:12 -0000 @@ -26,6 +26,7 @@ import org.eclipse.jdt.internal.compiler.lookup.FieldBinding; import org.eclipse.jdt.internal.compiler.lookup.MethodScope; import org.eclipse.jdt.internal.compiler.lookup.SourceTypeBinding; +import org.eclipse.jdt.internal.compiler.lookup.SyntheticMethodBinding; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.eclipse.jdt.internal.compiler.parser.Parser; import org.eclipse.jdt.internal.compiler.problem.AbortMethod; @@ -191,16 +192,44 @@ // generate static fields/initializers/enum constants final FieldDeclaration[] fieldDeclarations = declaringType.fields; BlockScope lastInitializerScope = null; + int remainingFieldCount = 0; if (TypeDeclaration.kind(declaringType.modifiers) == TypeDeclaration.ENUM_DECL) { - int enumCount = 0; - int remainingFieldCount = 0; - if (fieldDeclarations != null) { + int enumCount = declaringType.enumConstantsCounter; + if (enumCount > 2000) { + // 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 > 2000) { + SyntheticMethodBinding syntheticMethod = declaringType.binding.addSyntheticMethodForEnumInitialization(begin, i); + codeStream.invoke(Opcodes.OPC_invokestatic, syntheticMethod, null /* default declaringClass */); + begin = -1; + count = 0; + } + } + } + } + if (count != 0) { + // add last synthetic method + SyntheticMethodBinding syntheticMethod = declaringType.binding.addSyntheticMethodForEnumInitialization(begin, max); + codeStream.invoke(Opcodes.OPC_invokestatic, syntheticMethod, null /* default declaringClass */); + } + } + } 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); - enumCount++; } else { remainingFieldCount++; } @@ -228,20 +257,24 @@ codeStream.fieldAccess(Opcodes.OPC_putstatic, declaringType.enumValuesSyntheticfield, null /* default declaringClass */); 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++) { + 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()) + if (!fieldDecl.isStatic()) { break; + } + remainingFieldCount--; lastInitializerScope = ((Initializer) fieldDecl).block.scope; fieldDecl.generateCode(staticInitializerScope, codeStream); break; case AbstractVariableDeclaration.FIELD : - if (!fieldDecl.binding.isStatic()) + if (!fieldDecl.binding.isStatic()) { break; + } + remainingFieldCount--; lastInitializerScope = null; fieldDecl.generateCode(staticInitializerScope, codeStream); break; Index: compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java,v retrieving revision 1.101 diff -u -r1.101 FieldDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java 1 Jul 2010 04:39:20 -0000 1.101 +++ compiler/org/eclipse/jdt/internal/compiler/ast/FieldDeclaration.java 20 Dec 2010 00:49:12 -0000 @@ -94,7 +94,7 @@ int pc = codeStream.position; boolean isStatic; if (this.initialization != null - && !((isStatic = this.binding.isStatic()) && this.binding.constant() != Constant.NotAConstant)) { + && !((isStatic = this.binding.isStatic()) && this.binding.constant() != Constant.NotAConstant)) { // non-static field, need receiver if (!isStatic) codeStream.aload_0(); Index: compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java,v retrieving revision 1.164 diff -u -r1.164 TypeDeclaration.java --- compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java 21 Jun 2010 09:47:48 -0000 1.164 +++ compiler/org/eclipse/jdt/internal/compiler/ast/TypeDeclaration.java 20 Dec 2010 00:49:13 -0000 @@ -55,6 +55,7 @@ public TypeDeclaration enclosingType; // for member types only public FieldBinding enumValuesSyntheticfield; // for enum + public int enumConstantsCounter; // 1.5 support public TypeParameter[] typeParameters; Index: compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java,v retrieving revision 1.179 diff -u -r1.179 CodeStream.java --- compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 9 Nov 2010 19:59:19 -0000 1.179 +++ compiler/org/eclipse/jdt/internal/compiler/codegen/CodeStream.java 20 Dec 2010 00:49:15 -0000 @@ -15,10 +15,13 @@ import org.eclipse.jdt.internal.compiler.CompilationResult; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration; import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.eclipse.jdt.internal.compiler.ast.Expression; +import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.OperatorIds; +import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.flow.UnconditionalFlowInfo; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; @@ -2445,7 +2448,24 @@ aload_2(); areturn(); } - +public void generateSyntheticBodyForEnumInitializationMethod(SyntheticMethodBinding methodBinding) { + // no local used + this.maxLocals = 0; + // generate all enum constants + SourceTypeBinding sourceTypeBinding = (SourceTypeBinding) methodBinding.declaringClass; + TypeDeclaration typeDeclaration = sourceTypeBinding.scope.referenceContext; + BlockScope staticInitializerScope = typeDeclaration.staticInitializerScope; + FieldDeclaration[] fieldDeclarations = typeDeclaration.fields; + for (int i = methodBinding.startIndex, max = methodBinding.endIndex; i < max; i++) { + FieldDeclaration fieldDecl = fieldDeclarations[i]; + if (fieldDecl.isStatic()) { + if (fieldDecl.getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { + fieldDecl.generateCode(staticInitializerScope, this); + } + } + } + return_(); +} public void generateSyntheticBodyForFieldReadAccess(SyntheticMethodBinding accessMethod) { initializeMaxLocals(accessMethod); FieldBinding fieldBinding = accessMethod.targetReadField; Index: compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java,v retrieving revision 1.183 diff -u -r1.183 SourceTypeBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 17 Dec 2010 06:40:13 -0000 1.183 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java 20 Dec 2010 00:49:15 -0000 @@ -480,6 +480,18 @@ } return accessMethod; } +public SyntheticMethodBinding addSyntheticMethodForEnumInitialization(int begin, int end) { + if (this.synthetics == null) + this.synthetics = new HashMap[MAX_SYNTHETICS]; + if (this.synthetics[SourceTypeBinding.METHOD_EMUL] == null) + this.synthetics[SourceTypeBinding.METHOD_EMUL] = new HashMap(5); + + SyntheticMethodBinding accessMethod = new SyntheticMethodBinding(this, begin, end); + SyntheticMethodBinding[] accessors = new SyntheticMethodBinding[2]; + this.synthetics[SourceTypeBinding.METHOD_EMUL].put(accessMethod.selector, accessors); + accessors[0] = accessMethod; + return accessMethod; +} /* Add a new synthetic access method for access to . * Must distinguish access method used for super access from others (need to use invokespecial bytecode) Answer the new method or the existing method if one already existed. @@ -1500,7 +1512,6 @@ public ReferenceBinding[] superInterfaces() { return this.superInterfaces; } - public SyntheticMethodBinding[] syntheticMethods() { if (this.synthetics == null || this.synthetics[SourceTypeBinding.METHOD_EMUL] == null Index: compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java,v retrieving revision 1.26 diff -u -r1.26 SyntheticMethodBinding.java --- compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java 7 Sep 2010 13:39:18 -0000 1.26 +++ compiler/org/eclipse/jdt/internal/compiler/lookup/SyntheticMethodBinding.java 20 Dec 2010 00:49:16 -0000 @@ -21,9 +21,13 @@ public FieldBinding targetWriteField; // write access to a field public MethodBinding targetMethod; // method or constructor public TypeBinding targetEnumType; // enum type - + public int purpose; + // fields used to generate enum constants when too many + public int startIndex; + public int endIndex; + public final static int FieldReadAccess = 1; // field read public final static int FieldWriteAccess = 2; // field write public final static int SuperFieldReadAccess = 3; // super field read @@ -35,6 +39,7 @@ public final static int EnumValues = 9; // enum #values() public final static int EnumValueOf = 10; // enum #valueOf(String) public final static int SwitchTable = 11; // switch table method + public final static int TooManyEnumsConstants = 12; // too many enum constants public int sourceStart = 0; // start position of the matching declaration public int index; // used for sorting access methods in the class file @@ -265,6 +270,26 @@ } } + /** + * Construct enum special methods: values or valueOf methods + */ + public SyntheticMethodBinding(SourceTypeBinding declaringEnum, int startIndex, int endIndex) { + this.declaringClass = declaringEnum; + SyntheticMethodBinding[] knownAccessMethods = declaringEnum.syntheticMethods(); + this.index = knownAccessMethods == null ? 0 : knownAccessMethods.length; + StringBuffer buffer = new StringBuffer(); + buffer.append(' ').append(TypeConstants.SYNTHETIC_ACCESS_METHOD_PREFIX).append(this.index); + this.selector = String.valueOf(buffer).toCharArray(); + this.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic; + this.tagBits |= (TagBits.AnnotationResolved | TagBits.DeprecatedAnnotationResolved); + this.purpose = SyntheticMethodBinding.TooManyEnumsConstants; + this.thrownExceptions = Binding.NO_EXCEPTIONS; + this.returnType = TypeBinding.VOID; + this.parameters = Binding.NO_PARAMETERS; + this.startIndex = startIndex; + this.endIndex = endIndex; + } + // Create a synthetic method that will simply call the super classes method. // Used when a public method is inherited from a non-public class into a public class. // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=288658 Index: compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java,v retrieving revision 1.421 diff -u -r1.421 Parser.java --- compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java 27 Oct 2010 02:55:30 -0000 1.421 +++ compiler/org/eclipse/jdt/internal/compiler/parser/Parser.java 20 Dec 2010 00:49:19 -0000 @@ -8277,92 +8277,93 @@ protected void dispatchDeclarationIntoEnumDeclaration(int length) { if (length == 0) - return; - int[] flag = new int[length + 1]; //plus one -- see - int size1 = 0, size2 = 0, size3 = 0; - TypeDeclaration enumDeclaration = (TypeDeclaration) this.astStack[this.astPtr - length]; - boolean hasAbstractMethods = false; - for (int i = length - 1; i >= 0; i--) { - ASTNode astNode = this.astStack[this.astPtr--]; - if (astNode instanceof AbstractMethodDeclaration) { - //methods and constructors have been regrouped into one single list - flag[i] = 2; - size2++; - if (((AbstractMethodDeclaration) astNode).isAbstract()) { - hasAbstractMethods = true; - } - } else if (astNode instanceof TypeDeclaration) { - flag[i] = 3; - size3++; - } else if (astNode instanceof FieldDeclaration) { - flag[i] = 1; - size1++; -// if(astNode instanceof EnumConstant) { -// EnumConstant constant = (EnumConstant) astNode; -// ((AllocationExpression)constant.initialization).type = new SingleTypeReference(enumDeclaration.name, -// (((long) enumDeclaration.sourceStart) << 32) + enumDeclaration.sourceEnd); -// } - } - } - - //arrays creation - if (size1 != 0) { - enumDeclaration.fields = new FieldDeclaration[size1]; - } - if (size2 != 0) { - enumDeclaration.methods = new AbstractMethodDeclaration[size2]; - if (hasAbstractMethods) enumDeclaration.bits |= ASTNode.HasAbstractMethods; - } - if (size3 != 0) { - enumDeclaration.memberTypes = new TypeDeclaration[size3]; - } - - //arrays fill up - size1 = size2 = size3 = 0; - int flagI = flag[0], start = 0; - int length2; - for (int end = 0; end <= length; end++) // the plus one allows to - { - if (flagI != flag[end]) //treat the last element as a ended flag..... - { //array copy - switch (flagI) { - case 1 : - size1 += (length2 = end - start); - System.arraycopy( - this.astStack, - this.astPtr + start + 1, - enumDeclaration.fields, - size1 - length2, - length2); - break; - case 2 : - size2 += (length2 = end - start); - System.arraycopy( - this.astStack, - this.astPtr + start + 1, - enumDeclaration.methods, - size2 - length2, - length2); - break; - case 3 : - size3 += (length2 = end - start); - System.arraycopy( - this.astStack, - this.astPtr + start + 1, - enumDeclaration.memberTypes, - size3 - length2, - length2); - break; - } - flagI = flag[start = end]; - } - } - - if (enumDeclaration.memberTypes != null) { - for (int i = enumDeclaration.memberTypes.length - 1; i >= 0; i--) { - enumDeclaration.memberTypes[i].enclosingType = enumDeclaration; - } - }} + return; + int[] flag = new int[length + 1]; //plus one -- see + int size1 = 0, size2 = 0, size3 = 0; + TypeDeclaration enumDeclaration = (TypeDeclaration) this.astStack[this.astPtr - length]; + boolean hasAbstractMethods = false; + int enumConstantsCounter = 0; + for (int i = length - 1; i >= 0; i--) { + ASTNode astNode = this.astStack[this.astPtr--]; + if (astNode instanceof AbstractMethodDeclaration) { + //methods and constructors have been regrouped into one single list + flag[i] = 2; + size2++; + if (((AbstractMethodDeclaration) astNode).isAbstract()) { + hasAbstractMethods = true; + } + } else if (astNode instanceof TypeDeclaration) { + flag[i] = 3; + size3++; + } else if (astNode instanceof FieldDeclaration) { + flag[i] = 1; + size1++; + if (((FieldDeclaration) astNode).getKind() == AbstractVariableDeclaration.ENUM_CONSTANT) { + enumConstantsCounter++; + } + } + } + + //arrays creation + if (size1 != 0) { + enumDeclaration.fields = new FieldDeclaration[size1]; + } + if (size2 != 0) { + enumDeclaration.methods = new AbstractMethodDeclaration[size2]; + if (hasAbstractMethods) enumDeclaration.bits |= ASTNode.HasAbstractMethods; + } + if (size3 != 0) { + enumDeclaration.memberTypes = new TypeDeclaration[size3]; + } + + //arrays fill up + size1 = size2 = size3 = 0; + int flagI = flag[0], start = 0; + int length2; + for (int end = 0; end <= length; end++) // the plus one allows to + { + if (flagI != flag[end]) //treat the last element as a ended flag..... + { //array copy + switch (flagI) { + case 1 : + size1 += (length2 = end - start); + System.arraycopy( + this.astStack, + this.astPtr + start + 1, + enumDeclaration.fields, + size1 - length2, + length2); + break; + case 2 : + size2 += (length2 = end - start); + System.arraycopy( + this.astStack, + this.astPtr + start + 1, + enumDeclaration.methods, + size2 - length2, + length2); + break; + case 3 : + size3 += (length2 = end - start); + System.arraycopy( + this.astStack, + this.astPtr + start + 1, + enumDeclaration.memberTypes, + size3 - length2, + length2); + break; + } + flagI = flag[start = end]; + } + } + + if (enumDeclaration.memberTypes != null) { + for (int i = enumDeclaration.memberTypes.length - 1; i >= 0; i--) { + enumDeclaration.memberTypes[i].enclosingType = enumDeclaration; + } + } + enumDeclaration.enumConstantsCounter = enumConstantsCounter; +} protected CompilationUnitDeclaration endParse(int act) { this.lastAct = act;