KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > compiler > ast > SynchronizedStatement


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

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(); //$NON-NLS-1$
27

28     // for local variables table attributes
29
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     // TODO (philippe) shouldn't it be protected by a check whether reachable statement ?
52

53     // mark the synthetic variable as being used
54
synchroVariable.useFlag = LocalVariableBinding.USED;
55
56     // simple propagation to subnodes
57
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     // optimizing code gen
67
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 /**
79  * Synchronized statement code generation
80  *
81  * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
82  * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
83  */

84 public void generateCode(BlockScope currentScope, CodeStream codeStream) {
85     if ((bits & IsReachable) == 0) {
86         return;
87     }
88     // in case the labels needs to be reinitialized
89
// when the code generation is restarted in wide mode
90
this.anyExceptionLabel = null;
91
92     int pc = codeStream.position;
93
94     // generate the synchronization expression
95
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         // only take the lock
104
codeStream.monitorenter();
105         codeStream.monitorexit();
106         if (scope != currentScope) {
107             codeStream.exitUserScope(scope);
108         }
109     } else {
110         // enter the monitor
111
codeStream.store(synchroVariable, true);
112         codeStream.monitorenter();
113
114         // generate the body of the synchronized block
115
this.enterAnyExceptionHandler(codeStream);
116         block.generateCode(scope, codeStream);
117         if (scope != currentScope) {
118             // close all locals defined in the synchronized block except the secret local
119
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         // generate the body of the exception handler
131
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         // May loose some local variable initializations : affecting the local variable attributes
141
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 /**
156  * @see SubRoutineStatement#generateSubRoutineInvocation(BlockScope, CodeStream, Object, int, LocalVariableBinding)
157  */

158 public boolean generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream, Object JavaDoc 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     // special scope for secret locals optimization.
167
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     //continue even on errors in order to have the TC done into the statements
190
synchroVariable = new LocalVariableBinding(SecretLocalDeclarationName, type, ClassFileConstants.AccDefault, false);
191     scope.addLocalVariable(synchroVariable);
192     synchroVariable.setConstant(Constant.NotAConstant); // not inlinable
193
expression.computeConversion(scope, type, type);
194     block.resolveUsing(scope);
195 }
196
197 public StringBuffer JavaDoc printStatement(int indent, StringBuffer JavaDoc output) {
198     printIndent(indent, output);
199     output.append("synchronized ("); //$NON-NLS-1$
200
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