KickJava   Java API By Example, From Geeks To Geeks.

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


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.impl.*;
15 import org.eclipse.jdt.internal.compiler.codegen.*;
16 import org.eclipse.jdt.internal.compiler.flow.*;
17 import org.eclipse.jdt.internal.compiler.lookup.*;
18
19 //dedicated treatment for the &&
20
public class AND_AND_Expression extends BinaryExpression {
21
22     int rightInitStateIndex = -1;
23     int mergedInitStateIndex = -1;
24
25     public AND_AND_Expression(Expression left, Expression right, int operator) {
26         super(left, right, operator);
27     }
28
29     public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
30
31         Constant cst = this.left.optimizedBooleanConstant();
32         boolean isLeftOptimizedTrue = cst != Constant.NotAConstant && cst.booleanValue() == true;
33         boolean isLeftOptimizedFalse = cst != Constant.NotAConstant && cst.booleanValue() == false;
34
35         if (isLeftOptimizedTrue) {
36             // TRUE && anything
37
// need to be careful of scenario:
38
// (x && y) && !z, if passing the left info to the right, it would
39
// be swapped by the !
40
FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo)
41                     .unconditionalInits();
42             mergedInfo = right.analyseCode(currentScope, flowContext, mergedInfo);
43             mergedInitStateIndex = currentScope.methodScope()
44                     .recordInitializationStates(mergedInfo);
45             return mergedInfo;
46         }
47
48         FlowInfo leftInfo = left.analyseCode(currentScope, flowContext, flowInfo);
49         // need to be careful of scenario:
50
// (x && y) && !z, if passing the left info to the right, it would be
51
// swapped by the !
52
FlowInfo rightInfo = leftInfo.initsWhenTrue().unconditionalCopy();
53         rightInitStateIndex = currentScope.methodScope().recordInitializationStates(rightInfo);
54
55         int previousMode = rightInfo.reachMode();
56         if (isLeftOptimizedFalse) {
57             rightInfo.setReachMode(FlowInfo.UNREACHABLE);
58         }
59         rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
60         FlowInfo mergedInfo = FlowInfo.conditional(
61                 rightInfo.safeInitsWhenTrue(),
62                 leftInfo.initsWhenFalse().unconditionalInits().mergedWith(
63                         rightInfo.initsWhenFalse().setReachMode(previousMode).unconditionalInits()));
64         // reset after trueMergedInfo got extracted
65
mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
66         return mergedInfo;
67     }
68
69     /**
70      * Code generation for a binary operation
71      */

72     public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
73
74         int pc = codeStream.position;
75         if (constant != Constant.NotAConstant) {
76             // inlined value
77
if (valueRequired)
78                 codeStream.generateConstant(constant, implicitConversion);
79             codeStream.recordPositionsFrom(pc, this.sourceStart);
80             return;
81         }
82         Constant cst = right.constant;
83         if (cst != Constant.NotAConstant) {
84             // <expr> && true --> <expr>
85
if (cst.booleanValue() == true) {
86                 this.left.generateCode(currentScope, codeStream, valueRequired);
87             } else {
88                 // <expr> && false --> false
89
this.left.generateCode(currentScope, codeStream, false);
90                 if (valueRequired) codeStream.iconst_0();
91             }
92             if (mergedInitStateIndex != -1) {
93                 codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
94             }
95             codeStream.generateImplicitConversion(implicitConversion);
96             codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);
97             codeStream.recordPositionsFrom(pc, this.sourceStart);
98             return;
99         }
100         
101         BranchLabel falseLabel = new BranchLabel(codeStream), endLabel;
102         cst = left.optimizedBooleanConstant();
103         boolean leftIsConst = cst != Constant.NotAConstant;
104         boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
105
106         cst = right.optimizedBooleanConstant();
107         boolean rightIsConst = cst != Constant.NotAConstant;
108         boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
109
110         generateOperands : {
111             if (leftIsConst) {
112                 left.generateCode(currentScope, codeStream, false);
113                 if (!leftIsTrue) {
114                     break generateOperands; // no need to generate right operand
115
}
116             } else {
117                 left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, true);
118                 // need value, e.g. if (a == 1 && ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a!=1
119
}
120             if (rightInitStateIndex != -1) {
121                 codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
122             }
123             if (rightIsConst) {
124                 right.generateCode(currentScope, codeStream, false);
125             } else {
126                 right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired);
127             }
128         }
129         if (mergedInitStateIndex != -1) {
130             codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
131         }
132         /*
133          * improving code gen for such a case: boolean b = i < 0 && false since
134          * the label has never been used, we have the inlined value on the
135          * stack.
136          */

137         if (valueRequired) {
138             if (leftIsConst && !leftIsTrue) {
139                 codeStream.iconst_0();
140                 codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);
141             } else {
142                 if (rightIsConst && !rightIsTrue) {
143                     codeStream.iconst_0();
144                     codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);
145                 } else {
146                     codeStream.iconst_1();
147                 }
148                 if (falseLabel.forwardReferenceCount() > 0) {
149                     if ((bits & IsReturnedValue) != 0) {
150                         codeStream.generateImplicitConversion(this.implicitConversion);
151                         codeStream.generateReturnBytecode(this);
152                         falseLabel.place();
153                         codeStream.iconst_0();
154                     } else {
155                         codeStream.goto_(endLabel = new BranchLabel(codeStream));
156                         codeStream.decrStackSize(1);
157                         falseLabel.place();
158                         codeStream.iconst_0();
159                         endLabel.place();
160                     }
161                 } else {
162                     falseLabel.place();
163                 }
164             }
165             codeStream.generateImplicitConversion(implicitConversion);
166             codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);
167         } else {
168             falseLabel.place();
169         }
170     }
171
172     /**
173      * Boolean operator code generation Optimized operations are: &&
174      */

175     public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel, boolean valueRequired) {
176
177         if (constant != Constant.NotAConstant) {
178             super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel,
179                     valueRequired);
180             return;
181         }
182
183         // <expr> && true --> <expr>
184
Constant cst = right.constant;
185         if (cst != Constant.NotAConstant && cst.booleanValue() == true) {
186             int pc = codeStream.position;
187             this.left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
188             if (mergedInitStateIndex != -1) {
189                 codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
190             }
191             codeStream.recordPositionsFrom(pc, this.sourceStart);
192             return;
193         }
194         cst = left.optimizedBooleanConstant();
195         boolean leftIsConst = cst != Constant.NotAConstant;
196         boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;
197
198         cst = right.optimizedBooleanConstant();
199         boolean rightIsConst = cst != Constant.NotAConstant;
200         boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;
201
202         // default case
203
generateOperands : {
204             if (falseLabel == null) {
205                 if (trueLabel != null) {
206                     // implicit falling through the FALSE case
207
BranchLabel internalFalseLabel = new BranchLabel(codeStream);
208                     left.generateOptimizedBoolean(currentScope, codeStream, null, internalFalseLabel, !leftIsConst);
209                     // need value, e.g. if (a == 1 && ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a!=1
210
if (leftIsConst && !leftIsTrue) {
211                         internalFalseLabel.place();
212                         break generateOperands; // no need to generate right operand
213
}
214                     if (rightInitStateIndex != -1) {
215                         codeStream
216                                 .addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
217                     }
218                     right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null,
219                             valueRequired && !rightIsConst);
220                     if (valueRequired && rightIsConst && rightIsTrue) {
221                         codeStream.goto_(trueLabel);
222                         codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);
223                     }
224                     internalFalseLabel.place();
225                 }
226             } else {
227                 // implicit falling through the TRUE case
228
if (trueLabel == null) {
229                     left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, !leftIsConst);
230                     // need value, e.g. if (a == 1 && ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a!=1
231
if (leftIsConst && !leftIsTrue) {
232                         if (valueRequired) codeStream.goto_(falseLabel);
233                         codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);
234                         break generateOperands; // no need to generate right operand
235
}
236                     if (rightInitStateIndex != -1) {
237                         codeStream
238                                 .addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
239                     }
240                     right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired && !rightIsConst);
241                     if (valueRequired && rightIsConst && !rightIsTrue) {
242                         codeStream.goto_(falseLabel);
243                         codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);
244                     }
245                 } else {
246                     // no implicit fall through TRUE/FALSE --> should never occur
247
}
248             }
249         }
250         if (mergedInitStateIndex != -1) {
251             codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
252         }
253     }
254
255     public boolean isCompactableOperation() {
256         return false;
257     }
258
259     public void traverse(ASTVisitor visitor, BlockScope scope) {
260         if (visitor.visit(this, scope)) {
261             left.traverse(visitor, scope);
262             right.traverse(visitor, scope);
263         }
264         visitor.endVisit(this, scope);
265     }
266 }
267
Popular Tags