<s> package org . eclipse . jdt . internal . compiler . ast ; import org . eclipse . jdt . internal . compiler . ASTVisitor ; import org . eclipse . jdt . internal . compiler . ClassFile ; import org . eclipse . jdt . internal . compiler . CompilationResult ; import org . eclipse . jdt . internal . compiler . codegen . BranchLabel ; import org . eclipse . jdt . internal . compiler . codegen . CodeStream ; import org . eclipse . jdt . internal . compiler . codegen . ConstantPool ; import org . eclipse . jdt . internal . compiler . codegen . Opcodes ; import org . eclipse . jdt . internal . compiler . flow . ExceptionHandlingFlowContext ; import org . eclipse . jdt . internal . compiler . flow . FlowInfo ; import org . eclipse . jdt . internal . compiler . flow . InitializationFlowContext ; import org . eclipse . jdt . internal . compiler . lookup . Binding ; import org . eclipse . jdt . internal . compiler . lookup . BlockScope ; import org . eclipse . jdt . internal . compiler . lookup . ClassScope ; 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 ; public class Clinit extends AbstractMethodDeclaration { private static int ENUM_CONSTANTS_THRESHOLD = 2000 ; private FieldBinding assertionSyntheticFieldBinding = null ; private FieldBinding classLiteralSyntheticField = null ; public Clinit ( CompilationResult compilationResult ) { super ( compilationResult ) ; this . modifiers = 0 ; this . selector = TypeConstants . CLINIT ; } public void analyseCode ( ClassScope classScope , InitializationFlowContext staticInitializerFlowContext , FlowInfo flowInfo ) { if ( this . ignoreFurtherInvestigation ) return ; try { ExceptionHandlingFlowContext clinitContext = new ExceptionHandlingFlowContext ( staticInitializerFlowContext . parent , this , Binding . NO_EXCEPTIONS , staticInitializerFlowContext , this . scope , FlowInfo . DEAD_END ) ; if ( ( flowInfo . tagBits & FlowInfo . UNREACHABLE_OR_DEAD ) == 0 ) { this . bits |= ASTNode . NeedFreeReturn ; } flowInfo = flowInfo . mergedWith ( staticInitializerFlowContext . initsOnReturn ) ; FieldBinding [ ] fields = this . scope . enclosingSourceType ( ) . fields ( ) ; for ( int i = 0 , count = fields . length ; i < count ; i ++ ) { FieldBinding field ; if ( ( field = fields [ i ] ) . isStatic ( ) && field . isFinal ( ) && ( ! flowInfo . isDefinitelyAssigned ( fields [ i ] ) ) ) { this . scope . problemReporter ( ) . uninitializedBlankFinalField ( field , this . scope . referenceType ( ) . declarationOf ( field . original ( ) ) ) ; } } staticInitializerFlowContext . checkInitializerExceptions ( this . scope , clinitContext , flowInfo ) ; } catch ( AbortMethod e ) { this . ignoreFurtherInvestigation = true ; } } public void generateCode ( ClassScope classScope , ClassFile classFile ) { int clinitOffset = 0 ; if ( this . ignoreFurtherInvestigation ) { return ; } boolean restart = false ; do { try { clinitOffset = classFile . contentsOffset ; this . generateCode ( classScope , classFile , clinitOffset ) ; restart = false ; } catch ( AbortMethod e ) { if ( e . compilationResult == CodeStream . RESTART_IN_WIDE_MODE ) { classFile . contentsOffset = clinitOffset ; classFile . methodCount -- ; classFile . codeStream . resetInWideMode ( ) ; restart = true ; } else if ( e . compilationResult == CodeStream . RESTART_CODE_GEN_FOR_UNUSED_LOCALS_MODE ) { classFile . contentsOffset = clinitOffset ; classFile . methodCount -- ; classFile . codeStream . resetForCodeGenUnusedLocals ( ) ; restart = true ; } else { classFile . contentsOffset = clinitOffset ; classFile . methodCount -- ; restart = false ; } } } while ( restart ) ; } 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 ; MethodScope staticInitializerScope = declaringType . staticInitializerScope ; staticInitializerScope . computeLocalVariablePositions ( 0 , codeStream ) ; if ( this . assertionSyntheticFieldBinding != null ) { 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 . fieldAccess ( Opcodes . OPC_putstatic , this . assertionSyntheticFieldBinding , null ) ; } final FieldDeclaration [ ] fieldDeclarations = declaringType . fields ; BlockScope lastInitializerScope = null ; int remainingFieldCount = 0 ; if ( TypeDeclaration . kind ( declaringType . modifiers ) == TypeDeclaration . ENUM_DECL ) { int enumCount = declaringType . enumConstantsCounter ; if ( enumCount > ENUM_CONSTANTS_THRESHOLD ) { 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 ; } } } } if ( count != 0 ) { 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 ++ ; } } } } 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 ] ; 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 ) { 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 -- ; lastInitializerScope = ( ( Initializer ) fieldDecl ) . block . scope ; fieldDecl . generateCode ( staticInitializerScope , codeStream ) ; break ; case AbstractVariableDeclaration . FIELD : if ( ! fieldDecl . binding . isStatic ( ) ) { break ; } remainingFieldCount -- ; 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 ; } } } } if ( codeStream . position == 0 ) { classFile . contentsOffset = clinitOffset ; classFile . methodCount -- ; constantPool . resetForClinit ( constantPoolIndex , constantPoolOffset ) ; } else { if ( ( this . bits & ASTNode . NeedFreeReturn ) != 0 ) { int before = codeStream . position ; codeStream . return_ ( ) ; if ( lastInitializerScope != null ) { codeStream . updateLastRecordedEndPC ( lastInitializerScope , before ) ; } } codeStream . recordPositionsFrom ( 0 , declaringType . sourceStart ) ; classFile . completeCodeAttributeForClinit ( codeAttributeOffset ) ; } } public boolean isClinit ( ) { return true ; } public boolean isInitializationMethod ( ) { return true ; } public boolean isStatic ( ) { return true ; } public void parseStatements ( Parser parser , CompilationUnitDeclaration unit ) { } public StringBuffer print ( int tab , StringBuffer output ) { printIndent ( tab , output ) . append ( "<clinit>()" ) ; printBody ( tab + 1 , output ) ; return output ; } public void resolve ( ClassScope classScope ) { this . scope = new MethodScope ( classScope , classScope . referenceContext , true ) ; } public void traverse ( ASTVisitor visitor , ClassScope classScope ) { visitor . visit ( this , classScope ) ; visitor . endVisit ( this , classScope ) ; } public void setAssertionSupport ( FieldBinding assertionSyntheticFieldBinding , boolean needClassLiteralField ) { this . assertionSyntheticFieldBinding = assertionSyntheticFieldBinding ; if ( needClassLiteralField ) { SourceTypeBinding sourceType = this . scope . outerMostClassScope ( ) . enclosingSourceType ( ) ; if ( ! sourceType . isInterface ( ) && ! sourceType . isBaseType ( ) ) { this . classLiteralSyntheticField = sourceType . addSyntheticFieldForClassLiteral ( sourceType , this . scope ) ; } } } } </s>