Makefile fixup
[org.ibex.tool.git] / repo / org.ibex.tool / src / org / eclipse / jdt / internal / compiler / ast / SynchronizedStatement.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-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.codegen.*;
15 import org.eclipse.jdt.internal.compiler.flow.*;
16 import org.eclipse.jdt.internal.compiler.lookup.*;
17
18 public class SynchronizedStatement extends SubRoutineStatement {
19
20         public Expression expression;
21         public Block block;
22         public BlockScope scope;
23         boolean blockExit;
24         public LocalVariableBinding synchroVariable;
25         static final char[] SecretLocalDeclarationName = " syncValue".toCharArray(); //$NON-NLS-1$
26
27         public SynchronizedStatement(
28                 Expression expression,
29                 Block statement,
30                 int s,
31                 int e) {
32
33                 this.expression = expression;
34                 this.block = statement;
35                 sourceEnd = e;
36                 sourceStart = s;
37         }
38
39         public FlowInfo analyseCode(
40                 BlockScope currentScope,
41                 FlowContext flowContext,
42                 FlowInfo flowInfo) {
43
44                 // mark the synthetic variable as being used
45                 synchroVariable.useFlag = LocalVariableBinding.USED;
46
47                 // simple propagation to subnodes
48                 flowInfo =
49                         block.analyseCode(
50                                 scope,
51                                 new InsideSubRoutineFlowContext(flowContext, this),
52                                 expression.analyseCode(scope, flowContext, flowInfo));
53
54                 // optimizing code gen
55                 this.blockExit = !flowInfo.isReachable();
56
57                 return flowInfo;
58         }
59
60         public boolean isSubRoutineEscaping() {
61
62                 return false;
63         }
64         
65         /**
66          * Synchronized statement code generation
67          *
68          * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
69          * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
70          */
71         public void generateCode(BlockScope currentScope, CodeStream codeStream) {
72
73                 if ((bits & IsReachableMASK) == 0) {
74                         return;
75                 }
76                 // in case the labels needs to be reinitialized
77                 // when the code generation is restarted in wide mode
78                 if (this.anyExceptionLabelsCount > 0) {
79                         this.anyExceptionLabels = NO_EXCEPTION_HANDLER;
80                         this.anyExceptionLabelsCount = 0;
81                 }
82                 int pc = codeStream.position;
83
84                 // generate the synchronization expression
85                 expression.generateCode(scope, codeStream, true);
86                 if (block.isEmptyBlock()) {
87                         if ((synchroVariable.type == LongBinding)
88                                 || (synchroVariable.type == DoubleBinding)) {
89                                 codeStream.dup2();
90                         } else {
91                                 codeStream.dup();
92                         }
93                         // only take the lock
94                         codeStream.monitorenter();
95                         codeStream.monitorexit();
96                 } else {
97                         // enter the monitor
98                         codeStream.store(synchroVariable, true);
99                         codeStream.monitorenter();
100
101                         // generate  the body of the synchronized block
102                         this.enterAnyExceptionHandler(codeStream);
103                         block.generateCode(scope, codeStream);
104                         Label endLabel = new Label(codeStream);
105                         if (!blockExit) {
106                                 codeStream.load(synchroVariable);
107                                 codeStream.monitorexit();
108                                 codeStream.goto_(endLabel);
109                         }
110                         // generate the body of the exception handler
111                         this.exitAnyExceptionHandler();
112                         this.placeAllAnyExceptionHandlers();
113                         codeStream.incrStackSize(1);
114                         codeStream.load(synchroVariable);
115                         codeStream.monitorexit();
116                         codeStream.athrow();
117                         if (!blockExit) {
118                                 endLabel.place();
119                         }
120                 }
121                 if (scope != currentScope) {
122                         codeStream.exitUserScope(scope);
123                 }
124                 codeStream.recordPositionsFrom(pc, this.sourceStart);
125         }
126
127         /* (non-Javadoc)
128          * @see org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement#generateSubRoutineInvocation(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.codegen.CodeStream)
129          */
130         public void generateSubRoutineInvocation(
131                         BlockScope currentScope,
132                         CodeStream codeStream) {
133
134                 codeStream.load(this.synchroVariable);
135                 codeStream.monitorexit();
136         }
137
138         public void resolve(BlockScope upperScope) {
139
140                 // special scope for secret locals optimization.
141                 scope = new BlockScope(upperScope);
142                 TypeBinding type = expression.resolveType(scope);
143                 if (type == null)
144                         return;
145                 switch (type.id) {
146                         case (T_boolean) :
147                         case (T_char) :
148                         case (T_float) :
149                         case (T_double) :
150                         case (T_byte) :
151                         case (T_short) :
152                         case (T_int) :
153                         case (T_long) :
154                                 scope.problemReporter().invalidTypeToSynchronize(expression, type);
155                                 break;
156                         case (T_void) :
157                                 scope.problemReporter().illegalVoidExpression(expression);
158                                 break;
159                         case (T_null) :
160                                 scope.problemReporter().invalidNullToSynchronize(expression);
161                                 break; 
162                 }
163                 //continue even on errors in order to have the TC done into the statements
164                 synchroVariable = new LocalVariableBinding(SecretLocalDeclarationName, type, AccDefault, false);
165                 scope.addLocalVariable(synchroVariable);
166                 synchroVariable.constant = NotAConstant; // not inlinable
167                 expression.implicitWidening(type, type);
168                 block.resolveUsing(scope);
169         }
170
171         public StringBuffer printStatement(int indent, StringBuffer output) {
172
173                 printIndent(indent, output);
174                 output.append("synchronized ("); //$NON-NLS-1$
175                 expression.printExpression(0, output).append(')');
176                 output.append('\n');
177                 return block.printStatement(indent + 1, output); 
178         }
179
180         public void traverse(
181                 ASTVisitor visitor,
182                 BlockScope blockScope) {
183
184                 if (visitor.visit(this, blockScope)) {
185                         expression.traverse(visitor, scope);
186                         block.traverse(visitor, scope);
187                 }
188                 visitor.endVisit(this, blockScope);
189         }
190 }