<s> package org . eclipse . jdt . internal . compiler . ast ; import org . eclipse . jdt . internal . compiler . ASTVisitor ; import org . eclipse . jdt . internal . compiler . classfmt . ClassFileConstants ; import org . eclipse . jdt . internal . compiler . codegen . * ; import org . eclipse . jdt . internal . compiler . flow . * ; import org . eclipse . jdt . internal . compiler . impl . Constant ; import org . eclipse . jdt . internal . compiler . lookup . * ; public class SynchronizedStatement extends SubRoutineStatement { public Expression expression ; public Block block ; public BlockScope scope ; public LocalVariableBinding synchroVariable ; static final char [ ] SecretLocalDeclarationName = " syncValue" . toCharArray ( ) ; int preSynchronizedInitStateIndex = - 1 ; int mergedSynchronizedInitStateIndex = - 1 ; public SynchronizedStatement ( Expression expression , Block statement , int s , int e ) { this . expression = expression ; this . block = statement ; this . sourceEnd = e ; this . sourceStart = s ; } public FlowInfo analyseCode ( BlockScope currentScope , FlowContext flowContext , FlowInfo flowInfo ) { this . preSynchronizedInitStateIndex = currentScope . methodScope ( ) . recordInitializationStates ( flowInfo ) ; this . synchroVariable . useFlag = LocalVariableBinding . USED ; flowInfo = this . block . analyseCode ( this . scope , new InsideSubRoutineFlowContext ( flowContext , this ) , this . expression . analyseCode ( this . scope , flowContext , flowInfo ) ) ; this . mergedSynchronizedInitStateIndex = currentScope . methodScope ( ) . recordInitializationStates ( flowInfo ) ; if ( ( flowInfo . tagBits & FlowInfo . UNREACHABLE_OR_DEAD ) != 0 ) { this . bits |= ASTNode . BlockExit ; } return flowInfo ; } public boolean isSubRoutineEscaping ( ) { return false ; } public void generateCode ( BlockScope currentScope , CodeStream codeStream ) { if ( ( this . bits & IsReachable ) == 0 ) { return ; } this . anyExceptionLabel = null ; int pc = codeStream . position ; this . expression . generateCode ( this . scope , codeStream , true ) ; if ( this . block . isEmptyBlock ( ) ) { switch ( this . synchroVariable . type . id ) { case TypeIds . T_long : case TypeIds . T_double : codeStream . dup2 ( ) ; break ; default : codeStream . dup ( ) ; break ; } codeStream . monitorenter ( ) ; codeStream . monitorexit ( ) ; if ( this . scope != currentScope ) { codeStream . exitUserScope ( this . scope ) ; } } else { codeStream . store ( this . synchroVariable , true ) ; codeStream . addVariable ( this . synchroVariable ) ; codeStream . monitorenter ( ) ; enterAnyExceptionHandler ( codeStream ) ; this . block . generateCode ( this . scope , codeStream ) ; if ( this . scope != currentScope ) { codeStream . exitUserScope ( this . scope , this . synchroVariable ) ; } BranchLabel endLabel = new BranchLabel ( codeStream ) ; if ( ( this . bits & ASTNode . BlockExit ) == 0 ) { codeStream . load ( this . synchroVariable ) ; codeStream . monitorexit ( ) ; exitAnyExceptionHandler ( ) ; codeStream . goto_ ( endLabel ) ; enterAnyExceptionHandler ( codeStream ) ; } codeStream . pushExceptionOnStack ( this . scope . getJavaLangThrowable ( ) ) ; if ( this . preSynchronizedInitStateIndex != - 1 ) { codeStream . removeNotDefinitelyAssignedVariables ( currentScope , this . preSynchronizedInitStateIndex ) ; } placeAllAnyExceptionHandler ( ) ; codeStream . load ( this . synchroVariable ) ; codeStream . monitorexit ( ) ; exitAnyExceptionHandler ( ) ; codeStream . athrow ( ) ; if ( this . mergedSynchronizedInitStateIndex != - 1 ) { codeStream . removeNotDefinitelyAssignedVariables ( currentScope , this . mergedSynchronizedInitStateIndex ) ; codeStream . addDefinitelyAssignedVariables ( currentScope , this . mergedSynchronizedInitStateIndex ) ; } if ( this . scope != currentScope ) { codeStream . removeVariable ( this . synchroVariable ) ; } if ( ( this . bits & ASTNode . BlockExit ) == 0 ) { endLabel . place ( ) ; } } codeStream . recordPositionsFrom ( pc , this . sourceStart ) ; } public boolean generateSubRoutineInvocation ( BlockScope currentScope , CodeStream codeStream , Object targetLocation , int stateIndex , LocalVariableBinding secretLocal ) { codeStream . load ( this . synchroVariable ) ; codeStream . monitorexit ( ) ; exitAnyExceptionHandler ( ) ; return false ; } public void resolve ( BlockScope upperScope ) { this . scope = new BlockScope ( upperScope ) ; TypeBinding type = this . expression . resolveType ( this . scope ) ; if ( type == null ) return ; switch ( type . id ) { case T_boolean : case T_char : case T_float : case T_double : case T_byte : case T_short : case T_int : case T_long : this . scope . problemReporter ( ) . invalidTypeToSynchronize ( this . expression , type ) ; break ; case T_void : this . scope . problemReporter ( ) . illegalVoidExpression ( this . expression ) ; break ; case T_null : this . scope . problemReporter ( ) . invalidNullToSynchronize ( this . expression ) ; break ; } this . synchroVariable = new LocalVariableBinding ( SecretLocalDeclarationName , type , ClassFileConstants . AccDefault , false ) ; this . scope . addLocalVariable ( this . synchroVariable ) ; this . synchroVariable . setConstant ( Constant . NotAConstant ) ; this . expression . computeConversion ( this . scope , type , type ) ; this . block . resolveUsing ( this . scope ) ; } public StringBuffer printStatement ( int indent , StringBuffer output ) { printIndent ( indent , output ) ; output . append ( "" ) ; this . expression . printExpression ( 0 , output ) . append ( ')' ) ; output . append ( '\n' ) ; return this . block . printStatement ( indent + 1 , output ) ; } public void traverse ( ASTVisitor visitor , BlockScope blockScope ) { if ( visitor . visit ( this , blockScope ) ) { this . expression . traverse ( visitor , this . scope ) ; this . block . traverse ( visitor , this . scope ) ; } visitor . endVisit ( this , blockScope ) ; } } </s>