1 11 package org.eclipse.jdt.internal.compiler.ast; 12 13 import org.eclipse.jdt.internal.compiler.ASTVisitor; 14 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; 15 import org.eclipse.jdt.internal.compiler.codegen.*; 16 import org.eclipse.jdt.internal.compiler.flow.*; 17 import org.eclipse.jdt.internal.compiler.impl.Constant; 18 import org.eclipse.jdt.internal.compiler.lookup.*; 19 20 public class SynchronizedStatement extends SubRoutineStatement { 21 22 public Expression expression; 23 public Block block; 24 public BlockScope scope; 25 public LocalVariableBinding synchroVariable; 26 static final char[] SecretLocalDeclarationName = " syncValue".toCharArray(); 28 int preSynchronizedInitStateIndex = -1; 30 int mergedSynchronizedInitStateIndex = -1; 31 32 public SynchronizedStatement( 33 Expression expression, 34 Block statement, 35 int s, 36 int e) { 37 38 this.expression = expression; 39 this.block = statement; 40 sourceEnd = e; 41 sourceStart = s; 42 } 43 44 public FlowInfo analyseCode( 45 BlockScope currentScope, 46 FlowContext flowContext, 47 FlowInfo flowInfo) { 48 49 this.preSynchronizedInitStateIndex = 50 currentScope.methodScope().recordInitializationStates(flowInfo); 51 53 synchroVariable.useFlag = LocalVariableBinding.USED; 55 56 flowInfo = 58 block.analyseCode( 59 scope, 60 new InsideSubRoutineFlowContext(flowContext, this), 61 expression.analyseCode(scope, flowContext, flowInfo)); 62 63 this.mergedSynchronizedInitStateIndex = 64 currentScope.methodScope().recordInitializationStates(flowInfo); 65 66 if ((flowInfo.tagBits & FlowInfo.UNREACHABLE) != 0) { 68 this.bits |= ASTNode.BlockExit; 69 } 70 71 return flowInfo; 72 } 73 74 public boolean isSubRoutineEscaping() { 75 return false; 76 } 77 78 84 public void generateCode(BlockScope currentScope, CodeStream codeStream) { 85 if ((bits & IsReachable) == 0) { 86 return; 87 } 88 this.anyExceptionLabel = null; 91 92 int pc = codeStream.position; 93 94 expression.generateCode(scope, codeStream, true); 96 if (block.isEmptyBlock()) { 97 if ((synchroVariable.type == TypeBinding.LONG) 98 || (synchroVariable.type == TypeBinding.DOUBLE)) { 99 codeStream.dup2(); 100 } else { 101 codeStream.dup(); 102 } 103 codeStream.monitorenter(); 105 codeStream.monitorexit(); 106 if (scope != currentScope) { 107 codeStream.exitUserScope(scope); 108 } 109 } else { 110 codeStream.store(synchroVariable, true); 112 codeStream.monitorenter(); 113 114 this.enterAnyExceptionHandler(codeStream); 116 block.generateCode(scope, codeStream); 117 if (scope != currentScope) { 118 codeStream.exitUserScope(scope, synchroVariable); 120 } 121 122 BranchLabel endLabel = new BranchLabel(codeStream); 123 if ((this.bits & ASTNode.BlockExit) == 0) { 124 codeStream.load(synchroVariable); 125 codeStream.monitorexit(); 126 this.exitAnyExceptionHandler(); 127 codeStream.goto_(endLabel); 128 this.enterAnyExceptionHandler(codeStream); 129 } 130 codeStream.pushOnStack(scope.getJavaLangThrowable()); 132 if (this.preSynchronizedInitStateIndex != -1) { 133 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preSynchronizedInitStateIndex); 134 } 135 this.placeAllAnyExceptionHandler(); 136 codeStream.load(synchroVariable); 137 codeStream.monitorexit(); 138 this.exitAnyExceptionHandler(); 139 codeStream.athrow(); 140 if (this.mergedSynchronizedInitStateIndex != -1) { 142 codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedSynchronizedInitStateIndex); 143 codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedSynchronizedInitStateIndex); 144 } 145 if (scope != currentScope) { 146 codeStream.removeVariable(this.synchroVariable); 147 } 148 if ((this.bits & ASTNode.BlockExit) == 0) { 149 endLabel.place(); 150 } 151 } 152 codeStream.recordPositionsFrom(pc, this.sourceStart); 153 } 154 155 158 public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object targetLocation, int stateIndex, LocalVariableBinding secretLocal) { 159 codeStream.load(this.synchroVariable); 160 codeStream.monitorexit(); 161 exitAnyExceptionHandler(); 162 return false; 163 } 164 165 public void resolve(BlockScope upperScope) { 166 scope = new BlockScope(upperScope); 168 TypeBinding type = expression.resolveType(scope); 169 if (type == null) 170 return; 171 switch (type.id) { 172 case T_boolean : 173 case T_char : 174 case T_float : 175 case T_double : 176 case T_byte : 177 case T_short : 178 case T_int : 179 case T_long : 180 scope.problemReporter().invalidTypeToSynchronize(expression, type); 181 break; 182 case T_void : 183 scope.problemReporter().illegalVoidExpression(expression); 184 break; 185 case T_null : 186 scope.problemReporter().invalidNullToSynchronize(expression); 187 break; 188 } 189 synchroVariable = new LocalVariableBinding(SecretLocalDeclarationName, type, ClassFileConstants.AccDefault, false); 191 scope.addLocalVariable(synchroVariable); 192 synchroVariable.setConstant(Constant.NotAConstant); expression.computeConversion(scope, type, type); 194 block.resolveUsing(scope); 195 } 196 197 public StringBuffer printStatement(int indent, StringBuffer output) { 198 printIndent(indent, output); 199 output.append("synchronized ("); expression.printExpression(0, output).append(')'); 201 output.append('\n'); 202 return block.printStatement(indent + 1, output); 203 } 204 205 public void traverse(ASTVisitor visitor, BlockScope blockScope) { 206 if (visitor.visit(this, blockScope)) { 207 expression.traverse(visitor, scope); 208 block.traverse(visitor, scope); 209 } 210 visitor.endVisit(this, blockScope); 211 } 212 } 213 | Popular Tags |