*** empty log message ***
diff --git a/changes.txt b/changes.txt
index 3f2aaa3..3a886ff 100644
--- a/changes.txt
+++ b/changes.txt
@@ -94,7 +94,7 @@
1GK7FHB: ITPJCORE:WIN2000 - JCK 1.4 - class from outer and static class from superclass in top-level nested class
1GK7FCN: ITPJCORE:WIN2000 - JCK 1.4 - class from outer and public static class from superclass in top-level nested class
1GK7F8L: ITPJCORE:WIN2000 - JCK 1.4 - class from outer and protected static class from superclass in top-level nested class
- 1GK7F4S: ITPJCORE:WIN2000 - JCK 1.4 -static class from outer and class from superclass in nested class
+ 1GK7F4S: ITPJCORE:WIN2000 - JCK 1.4 - static class from outer and class from superclass in nested class
1GK7EZB: ITPJCORE:WIN2000 - JCK 1.4 - static class from outer and public class from superclass in nested class
1GK7EVB: ITPJCORE:WIN2000 - JCK 1.4 - static class from outer and protected class from superclass in nested class
1GK7ERE: ITPJCORE:WIN2000 - JCK 1.4 - static class from outer and static class from superclass in nested class
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
index d58afc7..5b31a4d 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/AND_AND_Expression.java
@@ -10,265 +10,282 @@
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
+//dedicated treatment for the &&
public class AND_AND_Expression extends BinaryExpression {
- //dedicated treatment for the &&
+
int rightInitStateIndex = -1;
int mergedInitStateIndex = -1;
-public AND_AND_Expression(Expression left, Expression right,int operator) {
- super(left,right,operator);
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+ public AND_AND_Expression(Expression left, Expression right, int operator) {
+ super(left, right, operator);
+ }
- Constant opConstant;
- if ((opConstant = left.constant) != NotAConstant) {
- if (opConstant.booleanValue() == true) {
- // TRUE && anything
- FlowInfo mergedInfo = right.analyseCode(currentScope, flowContext, flowInfo);
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
- return mergedInfo;
- } else {
- // FALSE && anything
- return flowInfo;
- }
- }
- if ((opConstant = right.constant) != NotAConstant) {
- if (opConstant.booleanValue() == true) {
- // anything && TRUE
- FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo);
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
- return mergedInfo;
- } else {
- // anything && FALSE
- // whatever is on the left, we will fail, so the result must merge the left inits when answering
- // initsWhenFalse. the initsWhenTrue are undetermined, since this path will be fake reachable...
- FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo);
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
- return mergedInfo;
- }
- }
- if ((opConstant = left.conditionalConstant()) != NotAConstant){
- if (opConstant.booleanValue() == false){
- // something eq. FALSE && anything
- FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo);
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
- right.analyseCode(currentScope, flowContext, mergedInfo.copy().markAsFakeReachable(true));
- return mergedInfo;
- }
- }
- FlowInfo leftInfo = left.analyseCode(currentScope, flowContext, flowInfo);
- FlowInfo rightInfo = leftInfo.initsWhenTrue().copy();
- rightInitStateIndex = currentScope.methodScope().recordInitializationStates(rightInfo);
- rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
- FlowInfo mergedInfo = FlowInfo.conditional(
- rightInfo.initsWhenTrue(),
- leftInfo.initsWhenFalse().unconditionalInits().mergedWith(rightInfo.initsWhenFalse().copy().unconditionalInits()));
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
- return mergedInfo;
-}
-public void computeConstant(BlockScope scope, int leftId, int rightId) {
- //the TC has been done so leftId and rightId are both equal to T_boolean
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
- Constant cst;
- if ((cst = left.constant) != NotAConstant) {
- if (cst.booleanValue() == false) { // false && x --> false
- constant = cst; // inlined to constant(false)
- } else { // true && x --> x
- if ((constant = right.constant) == NotAConstant) {
- // compute conditionalConstant
- optimizedBooleanConstant(leftId, (bits & OperatorMASK) >> OperatorSHIFT, rightId);
+ Constant opConstant = left.conditionalConstant();
+ if (opConstant != NotAConstant) {
+ if (opConstant.booleanValue() == true) {
+ // TRUE && anything
+ // need to be careful of scenario:
+ // (x && y) && !z, if passing the left info to the right, it would be swapped by the !
+ FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+ mergedInfo = right.analyseCode(currentScope, flowContext, mergedInfo);
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergedInfo);
+ return mergedInfo;
}
}
- } else {
- constant = NotAConstant;
- // compute conditionalConstant
- optimizedBooleanConstant(leftId, (bits & OperatorMASK) >> OperatorSHIFT, rightId);
+ FlowInfo leftInfo = left.analyseCode(currentScope, flowContext, flowInfo);
+ // need to be careful of scenario:
+ // (x && y) && !z, if passing the left info to the right, it would be swapped by the !
+ FlowInfo rightInfo = leftInfo.initsWhenTrue().unconditionalInits().copy();
+ if (opConstant != NotAConstant && opConstant.booleanValue() == false) rightInfo.markAsFakeReachable(true);
+
+ rightInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(rightInfo);
+ rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
+ FlowInfo mergedInfo =
+ FlowInfo.conditional(
+ rightInfo.initsWhenTrue().copy(),
+ leftInfo.initsWhenFalse().copy().unconditionalInits().mergedWith(
+ rightInfo.initsWhenFalse().copy().unconditionalInits()));
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergedInfo);
+ return mergedInfo;
}
-}
-/**
- * Code generation for a binary operation
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
- int pc = codeStream.position;
- Label falseLabel, endLabel;
- if (constant != Constant.NotAConstant) {
- // inlined value
- if (valueRequired)
- codeStream.generateConstant(constant, implicitConversion);
- codeStream.recordPositionsFrom(pc, this);
- return;
- }
- bits |= OnlyValueRequiredMASK;
- generateOptimizedConditionalAnd(currentScope, codeStream, null, (falseLabel = new Label(codeStream)), valueRequired);
- /* improving code gen for such a case: boolean b = i < 0 && false
- * since the label has never been used, we have the inlined value on the stack. */
- if (falseLabel.hasForwardReferences()) {
- if (valueRequired) {
- codeStream.iconst_1();
- if ((bits & ValueForReturnMASK) != 0) {
- codeStream.ireturn();
- falseLabel.place();
- codeStream.iconst_0();
- } else {
- codeStream.goto_(endLabel = new Label(codeStream));
- codeStream.decrStackSize(1);
- falseLabel.place();
- codeStream.iconst_0();
- endLabel.place();
- }
- } else {
- falseLabel.place();
- }
- }
- if (valueRequired) {
- codeStream.generateImplicitConversion(implicitConversion);
- }
- codeStream.recordPositionsFrom(pc, this);
-}
-/**
- * Boolean operator code generation
- * Optimized operations are: &&
- */
-public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
- if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
+
+ /**
+ * Code generation for a binary operation
+ */
+ public void generateCode(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ boolean valueRequired) {
+
int pc = codeStream.position;
- if (constant.booleanValue() == true) {
- // constant == true
+ Label falseLabel, endLabel;
+ if (constant != Constant.NotAConstant) {
+ // inlined value
+ if (valueRequired)
+ codeStream.generateConstant(constant, implicitConversion);
+ codeStream.recordPositionsFrom(pc, this);
+ return;
+ }
+ bits |= OnlyValueRequiredMASK;
+ generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ (falseLabel = new Label(codeStream)),
+ valueRequired);
+ /* improving code gen for such a case: boolean b = i < 0 && false
+ * since the label has never been used, we have the inlined value on the stack. */
+ if (falseLabel.hasForwardReferences()) {
if (valueRequired) {
- if (falseLabel == null) {
- // implicit falling through the FALSE case
- if (trueLabel != null) {
- codeStream.goto_(trueLabel);
- }
+ codeStream.iconst_1();
+ if ((bits & ValueForReturnMASK) != 0) {
+ codeStream.ireturn();
+ falseLabel.place();
+ codeStream.iconst_0();
+ } else {
+ codeStream.goto_(endLabel = new Label(codeStream));
+ codeStream.decrStackSize(1);
+ falseLabel.place();
+ codeStream.iconst_0();
+ endLabel.place();
}
- }
- } else {
- if (valueRequired) {
- if (falseLabel != null) {
- // implicit falling through the TRUE case
- if (trueLabel == null) {
- codeStream.goto_(falseLabel);
- }
- }
+ } else {
+ falseLabel.place();
}
}
+ if (valueRequired) {
+ codeStream.generateImplicitConversion(implicitConversion);
+ }
codeStream.recordPositionsFrom(pc, this);
- return;
}
- generateOptimizedConditionalAnd(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
-}
-/**
- * Boolean generation for &&
- */
-public void generateOptimizedConditionalAnd(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
- int pc = codeStream.position;
- Constant condConst;
- if ((condConst = left.conditionalConstant()) != NotAConstant) {
- if (condConst.booleanValue() == true) {
- // <something equivalent to true> && x
- left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, false);
- if (rightInitStateIndex != -1){
- codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
- }
- if ((bits & OnlyValueRequiredMASK) != 0){
- right.generateCode(currentScope, codeStream, valueRequired);
- } else {
- right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
- }
- } else {
- // <something equivalent to false> && x
- left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, false);
- if (valueRequired) {
+ /**
+ * Boolean operator code generation
+ * Optimized operations are: &&
+ */
+ public void generateOptimizedBoolean(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ Label trueLabel,
+ Label falseLabel,
+ boolean valueRequired) {
+ if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
+ super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+ return;
+ }
+ int pc = codeStream.position;
+ Constant condConst;
+ if ((condConst = left.conditionalConstant()) != NotAConstant) {
+ if (condConst.booleanValue() == true) {
+ // <something equivalent to true> && x
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
if ((bits & OnlyValueRequiredMASK) != 0) {
- codeStream.iconst_0();
+ right.generateCode(currentScope, codeStream, valueRequired);
} else {
- if (falseLabel != null) {
- // implicit falling through the TRUE case
- codeStream.goto_(falseLabel);
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ valueRequired);
+ }
+ } else {
+ // <something equivalent to false> && x
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (valueRequired) {
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ codeStream.iconst_0();
+ } else {
+ if (falseLabel != null) {
+ // implicit falling through the TRUE case
+ codeStream.goto_(falseLabel);
+ }
}
}
}
+ codeStream.recordPositionsFrom(pc, this);
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
+ }
+ return;
}
- codeStream.recordPositionsFrom(pc, this);
- if (mergedInitStateIndex != -1){
- codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
- }
- return;
- }
- if ((condConst = right.conditionalConstant()) != NotAConstant) {
- if (condConst.booleanValue() == true) {
- // x && <something equivalent to true>
- if ((bits & OnlyValueRequiredMASK) != 0){
- left.generateCode(currentScope, codeStream, valueRequired);
- } else {
- left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
- }
- if (rightInitStateIndex != -1){
- codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
- }
- right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, false);
- } else {
- // x && <something equivalent to false>
- left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, false);
- if (rightInitStateIndex != -1){
- codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
- }
- right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, false);
- if (valueRequired) {
+ if ((condConst = right.conditionalConstant()) != NotAConstant) {
+ if (condConst.booleanValue() == true) {
+ // x && <something equivalent to true>
if ((bits & OnlyValueRequiredMASK) != 0) {
- codeStream.iconst_0();
+ left.generateCode(currentScope, codeStream, valueRequired);
} else {
- if (falseLabel != null) {
- // implicit falling through the TRUE case
- codeStream.goto_(falseLabel);
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ valueRequired);
+ }
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ } else {
+ // x && <something equivalent to false>
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (valueRequired) {
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ codeStream.iconst_0();
+ } else {
+ if (falseLabel != null) {
+ // implicit falling through the TRUE case
+ codeStream.goto_(falseLabel);
+ }
}
}
}
+ codeStream.recordPositionsFrom(pc, this);
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
+ }
+ return;
+ }
+ // default case
+ if (falseLabel == null) {
+ if (trueLabel != null) {
+ // implicit falling through the FALSE case
+ Label internalFalseLabel = new Label(codeStream);
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ internalFalseLabel,
+ true);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ null,
+ valueRequired);
+ internalFalseLabel.place();
+ }
+ } else {
+ // implicit falling through the TRUE case
+ if (trueLabel == null) {
+ left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, true);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ falseLabel,
+ valueRequired);
+ } else {
+ // no implicit fall through TRUE/FALSE --> should never occur
+ }
}
codeStream.recordPositionsFrom(pc, this);
- if (mergedInitStateIndex != -1){
- codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
- }
- return;
- }
- // default case
- if (falseLabel == null) {
- if (trueLabel != null) {
- // implicit falling through the FALSE case
- Label internalFalseLabel = new Label(codeStream);
- left.generateOptimizedBoolean(currentScope, codeStream, null, internalFalseLabel, true);
- if (rightInitStateIndex != -1){
- codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
- }
- right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, valueRequired);
- internalFalseLabel.place();
- }
- } else {
- // implicit falling through the TRUE case
- if (trueLabel == null) {
- left.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, true);
- if (rightInitStateIndex != -1){
- codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
- }
- right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired);
- } else {
- // no implicit fall through TRUE/FALSE --> should never occur
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
}
}
- codeStream.recordPositionsFrom(pc, this);
- if (mergedInitStateIndex != -1){
- codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+
+ public boolean isCompactableOperation() {
+ return false;
}
-}
-public boolean isCompactableOperation() {
- return false;
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
- if (visitor.visit(this, scope)) {
- left.traverse(visitor, scope);
- right.traverse(visitor, scope);
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ left.traverse(visitor, scope);
+ right.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
}
- visitor.endVisit(this, scope);
-}
-}
+}
\ No newline at end of file
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
index 94d69a8..57aae22 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/BinaryExpression.java
@@ -519,28 +519,7 @@
public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
- int pc = codeStream.position;
- if (constant.booleanValue() == true) {
- // constant == true
- if (valueRequired) {
- if (falseLabel == null) {
- // implicit falling through the FALSE case
- if (trueLabel != null) {
- codeStream.goto_(trueLabel);
- }
- }
- }
- } else {
- if (valueRequired) {
- if (falseLabel != null) {
- // implicit falling through the TRUE case
- if (trueLabel == null) {
- codeStream.goto_(falseLabel);
- }
- }
- }
- }
- codeStream.recordPositionsFrom(pc, this);
+ super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
return;
}
switch((bits & OperatorMASK) >> OperatorSHIFT){
@@ -1309,7 +1288,7 @@
return;
} else { //left is equivalent to false
if ((cst = right.conditionalConstant()) != NotAConstant) {
- optimizedBooleanConstant = Constant.fromValue(!cst.booleanValue()); // the conditional result is equivalent to the opposite of the right conditional value
+ optimizedBooleanConstant = cst;
}
return;
}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
index 279d0bf..228624d 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/ConditionalExpression.java
@@ -11,6 +11,7 @@
import org.eclipse.jdt.internal.compiler.lookup.*;
public class ConditionalExpression extends OperatorExpression {
+
public Expression condition, valueIfTrue, valueIfFalse;
private int returnTypeSlotSize = 1;
@@ -18,266 +19,378 @@
int thenInitStateIndex = -1;
int elseInitStateIndex = -1;
int mergedInitStateIndex = -1;
-public ConditionalExpression(Expression condition, Expression valueIfTrue, Expression valueIfFalse) {
- this.condition = condition;
- this.valueIfTrue = valueIfTrue;
- this.valueIfFalse = valueIfFalse;
- sourceStart = condition.sourceStart ;
- sourceEnd = valueIfFalse.sourceEnd;
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
- Constant inlinedCondition = condition.constant;
- if (inlinedCondition == NotAConstant) inlinedCondition = condition.conditionalConstant();
- if (inlinedCondition != NotAConstant) {
- if (inlinedCondition.booleanValue() == true) {
- FlowInfo resultInfo = valueIfTrue.analyseCode(currentScope, flowContext, flowInfo);
- // analyse valueIfFalse, but do not take into account any of its infos
- valueIfFalse.analyseCode(currentScope, flowContext, flowInfo.copy().markAsFakeReachable(true));
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(resultInfo);
- return resultInfo;
- } else {
- // analyse valueIfTrue, but do not take into account any of its infos
- valueIfTrue.analyseCode(currentScope, flowContext, flowInfo.copy().markAsFakeReachable(true));
- FlowInfo mergeInfo = valueIfFalse.analyseCode(currentScope, flowContext, flowInfo);
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergeInfo);
- return mergeInfo;
- }
- }
- // notice that the receiver investigation is not performed in the previous case, since there is
- // not a chance it is worth trying to check anything on a constant expression.
- flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
-
- // store a copy of the merged info, so as to compute the local variable attributes afterwards
- FlowInfo trueInfo = flowInfo.initsWhenTrue();
- thenInitStateIndex = currentScope.methodScope().recordInitializationStates(trueInfo);
- FlowInfo falseInfo = flowInfo.initsWhenFalse();
- elseInitStateIndex = currentScope.methodScope().recordInitializationStates(falseInfo);
- // propagate analysis
- trueInfo = valueIfTrue.analyseCode(currentScope, flowContext, trueInfo.copy());
- falseInfo = valueIfFalse.analyseCode(currentScope, flowContext, falseInfo.copy());
-
- // merge back using a conditional info - 1GK2BLM
- // if ((t && (v = t)) ? t : t && (v = f)) r = v; -- ok
- FlowInfo mergedInfo = FlowInfo.conditional(
- trueInfo.initsWhenTrue().unconditionalInits().mergedWith(
- falseInfo.initsWhenTrue().unconditionalInits()),
- falseInfo.initsWhenFalse().unconditionalInits().mergedWith(
- falseInfo.initsWhenFalse().unconditionalInits()));
-/*
- FlowInfo mergedInfo = valueIfTrue.analyseCode(
- currentScope,
- flowContext,
- flowInfo.initsWhenTrue().copy()).
- unconditionalInits().
- mergedWith(
- valueIfFalse.analyseCode(
- currentScope,
- flowContext,
- flowInfo.initsWhenFalse().copy()).
- unconditionalInits());
-*/
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
- return mergedInfo;
-}
-/**
- * Code generation for the conditional operator ?:
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param valueRequired boolean
-*/
-public void generateCode(
- BlockScope currentScope,
- CodeStream codeStream,
- boolean valueRequired) {
-
- /* Reset the selector of the message pattern to use the optimized selectors,
- * when compiling full Java messages, if compiling macroexpanded controls, then
- * the selector is supposed correctly positionned.
- */
-
- int pc = codeStream.position, divergePC;
- Label endifLabel, falseLabel;
- if (constant != NotAConstant) {
- if (valueRequired)
- codeStream.generateConstant(constant, implicitConversion);
- codeStream.recordPositionsFrom(pc, this);
- return;
+ public ConditionalExpression(
+ Expression condition,
+ Expression valueIfTrue,
+ Expression valueIfFalse) {
+ this.condition = condition;
+ this.valueIfTrue = valueIfTrue;
+ this.valueIfFalse = valueIfFalse;
+ sourceStart = condition.sourceStart;
+ sourceEnd = valueIfFalse.sourceEnd;
}
- Constant cst = condition.constant;
- Constant condCst = condition.conditionalConstant();
- boolean needTruePart =
- !(((cst != NotAConstant) && (cst.booleanValue() == false))
- || ((condCst != NotAConstant) && (condCst.booleanValue() == false)));
- boolean needFalsePart =
- !(((cst != NotAConstant) && (cst.booleanValue() == true))
- || ((condCst != NotAConstant) && (condCst.booleanValue() == true)));
-
- endifLabel = new Label(codeStream);
-
- // Generate code for the condition
- boolean needConditionValue = (cst == NotAConstant) && (condCst == NotAConstant);
- condition.generateOptimizedBoolean(
- currentScope,
- codeStream,
- null,
- (falseLabel = new Label(codeStream)),
- needConditionValue);
-
- if (thenInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- thenInitStateIndex);
- codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
- }
-
- // Then code generation
- if (needTruePart) {
- valueIfTrue.generateCode(currentScope, codeStream, valueRequired);
-
- if (needFalsePart) {
- // Jump over the else part
- int position = codeStream.position;
- codeStream.goto_(endifLabel);
- codeStream.updateLastRecordedEndPC(position);
- // Tune codestream stack size
- if (valueRequired) {
- codeStream.decrStackSize(returnTypeSlotSize);
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
+ Constant conditionConstant = condition.conditionalConstant();
+ if (conditionConstant != NotAConstant) {
+ if (conditionConstant.booleanValue() == true) {
+ // TRUE ? left : right
+ FlowInfo resultInfo =
+ valueIfTrue.analyseCode(currentScope, flowContext, flowInfo);
+ // analyse valueIfFalse, but do not take into account any of its infos
+ valueIfFalse.analyseCode(
+ currentScope,
+ flowContext,
+ flowInfo.copy().markAsFakeReachable(true));
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(resultInfo);
+ return resultInfo;
+ } else {
+ // FALSE ? left : right
+ // analyse valueIfTrue, but do not take into account any of its infos
+ valueIfTrue.analyseCode(
+ currentScope,
+ flowContext,
+ flowInfo.copy().markAsFakeReachable(true));
+ FlowInfo mergeInfo =
+ valueIfFalse.analyseCode(currentScope, flowContext, flowInfo);
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergeInfo);
+ return mergeInfo;
}
}
+ // notice that the receiver investigation is not performed in the previous case, since there is
+ // not a chance it is worth trying to check anything on a constant expression.
+ flowInfo = condition.analyseCode(currentScope, flowContext, flowInfo);
+ // store a copy of the merged info, so as to compute the local variable attributes afterwards
+ FlowInfo trueInfo = flowInfo.initsWhenTrue();
+ thenInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(trueInfo);
+ FlowInfo falseInfo = flowInfo.initsWhenFalse();
+ elseInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(falseInfo);
+
+ // propagate analysis
+ trueInfo = valueIfTrue.analyseCode(currentScope, flowContext, trueInfo.copy());
+ falseInfo =
+ valueIfFalse.analyseCode(currentScope, flowContext, falseInfo.copy());
+
+ // merge back using a conditional info - 1GK2BLM
+ // if ((t && (v = t)) ? t : t && (v = f)) r = v; -- ok
+ FlowInfo mergedInfo =
+ FlowInfo.conditional(
+ trueInfo.initsWhenTrue().copy().unconditionalInits().mergedWith( // must copy, since could be shared with trueInfo.initsWhenFalse()...
+ falseInfo.initsWhenTrue().copy().unconditionalInits()),
+ trueInfo.initsWhenFalse().unconditionalInits().mergedWith(
+ falseInfo.initsWhenFalse().unconditionalInits()));
+ /*
+ FlowInfo mergedInfo = valueIfTrue.analyseCode(
+ currentScope,
+ flowContext,
+ flowInfo.initsWhenTrue().copy()).
+ unconditionalInits().
+ mergedWith(
+ valueIfFalse.analyseCode(
+ currentScope,
+ flowContext,
+ flowInfo.initsWhenFalse().copy()).
+ unconditionalInits());
+ */
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergedInfo);
+ return mergedInfo;
}
- if (needFalsePart) {
- falseLabel.place();
- if (elseInitStateIndex != -1) {
+
+ /**
+ * Code generation for the conditional operator ?:
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+ public void generateCode(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ boolean valueRequired) {
+
+ int pc = codeStream.position;
+ Label endifLabel, falseLabel;
+ if (constant != NotAConstant) {
+ if (valueRequired)
+ codeStream.generateConstant(constant, implicitConversion);
+ codeStream.recordPositionsFrom(pc, this);
+ return;
+ }
+ Constant cst = condition.constant;
+ Constant condCst = condition.conditionalConstant();
+ boolean needTruePart =
+ !(((cst != NotAConstant) && (cst.booleanValue() == false))
+ || ((condCst != NotAConstant) && (condCst.booleanValue() == false)));
+ boolean needFalsePart =
+ !(((cst != NotAConstant) && (cst.booleanValue() == true))
+ || ((condCst != NotAConstant) && (condCst.booleanValue() == true)));
+ endifLabel = new Label(codeStream);
+
+ // Generate code for the condition
+ boolean needConditionValue = (cst == NotAConstant) && (condCst == NotAConstant);
+ condition.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ (falseLabel = new Label(codeStream)),
+ needConditionValue);
+
+ if (thenInitStateIndex != -1) {
codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- elseInitStateIndex);
- codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
+ currentScope,
+ thenInitStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
}
- valueIfFalse.generateCode(currentScope, codeStream, valueRequired);
+ // Then code generation
+ if (needTruePart) {
+ valueIfTrue.generateCode(currentScope, codeStream, valueRequired);
+ if (needFalsePart) {
+ // Jump over the else part
+ int position = codeStream.position;
+ codeStream.goto_(endifLabel);
+ codeStream.updateLastRecordedEndPC(position);
+ // Tune codestream stack size
+ if (valueRequired) {
+ codeStream.decrStackSize(returnTypeSlotSize);
+ }
+ }
+ }
+ if (needFalsePart) {
+ falseLabel.place();
+ if (elseInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ elseInitStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
+ }
+ valueIfFalse.generateCode(currentScope, codeStream, valueRequired);
+ // End of if statement
+ endifLabel.place();
+ }
+ // May loose some local variable initializations : affecting the local variable attributes
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
+ }
+ // implicit conversion
+ if (valueRequired)
+ codeStream.generateImplicitConversion(implicitConversion);
+ codeStream.recordPositionsFrom(pc, this);
+ }
- // End of if statement
- endifLabel.place();
- }
- // May loose some local variable initializations : affecting the local variable attributes
- if (mergedInitStateIndex != -1) {
- codeStream.removeNotDefinitelyAssignedVariables(
- currentScope,
- mergedInitStateIndex);
- }
- // implicit conversion
- if (valueRequired)
- codeStream.generateImplicitConversion(implicitConversion);
- codeStream.recordPositionsFrom(pc, this);
-}
-public TypeBinding resolveType(BlockScope scope) {
- // specs p.368
- constant = NotAConstant;
- TypeBinding condTb = condition.resolveTypeExpecting(scope, BooleanBinding);
- TypeBinding trueTb = valueIfTrue.resolveType(scope);
- TypeBinding falseTb = valueIfFalse.resolveType(scope);
- if (condTb == null || trueTb == null || falseTb == null)
- return null;
+ /**
+ * Optimized boolean code generation for the conditional operator ?:
+ */
+ public void generateOptimizedBoolean(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ Label trueLabel,
+ Label falseLabel,
+ boolean valueRequired) {
- // Propagate the constant value from the valueIfTrue and valueIFFalse expression if it is possible
- if (condition.constant != NotAConstant && valueIfTrue.constant != NotAConstant && valueIfFalse.constant != NotAConstant) {
- // all terms are constant expression so we can propagate the constant
- // from valueIFTrue or valueIfFalse to teh receiver constant
- constant = (condition.constant.booleanValue()) ? valueIfTrue.constant : valueIfFalse.constant;
+ if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean) // constant
+ || (valueIfTrue.implicitConversion >> 4) != T_boolean) { // non boolean values
+ super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+ return;
+ }
+ int pc = codeStream.position;
+ Constant cst = condition.constant;
+ Constant condCst = condition.conditionalConstant();
+ boolean needTruePart =
+ !(((cst != NotAConstant) && (cst.booleanValue() == false))
+ || ((condCst != NotAConstant) && (condCst.booleanValue() == false)));
+ boolean needFalsePart =
+ !(((cst != NotAConstant) && (cst.booleanValue() == true))
+ || ((condCst != NotAConstant) && (condCst.booleanValue() == true)));
+
+ Label internalFalseLabel, endifLabel = new Label(codeStream);
+
+ // Generate code for the condition
+ boolean needConditionValue = (cst == NotAConstant) && (condCst == NotAConstant);
+ condition.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ internalFalseLabel = new Label(codeStream),
+ needConditionValue);
+
+ if (thenInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ thenInitStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, thenInitStateIndex);
+ }
+ // Then code generation
+ if (needTruePart) {
+ valueIfTrue.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+
+ if (needFalsePart) {
+ // Jump over the else part
+ int position = codeStream.position;
+ codeStream.goto_(endifLabel);
+ codeStream.updateLastRecordedEndPC(position);
+ // Tune codestream stack size
+ //if (valueRequired) {
+ // codeStream.decrStackSize(returnTypeSlotSize);
+ //}
+ }
+ }
+ if (needFalsePart) {
+ internalFalseLabel.place();
+ if (elseInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ elseInitStateIndex);
+ codeStream.addDefinitelyAssignedVariables(currentScope, elseInitStateIndex);
+ }
+ valueIfFalse.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+
+ // End of if statement
+ endifLabel.place();
+ }
+ // May loose some local variable initializations : affecting the local variable attributes
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
+ }
+ // no implicit conversion for boolean values
+ codeStream.recordPositionsFrom(pc, this);
}
- if (trueTb == falseTb) { // harmed the implicit conversion
- valueIfTrue.implicitWidening(trueTb, trueTb);
- valueIfFalse.implicitConversion = valueIfTrue.implicitConversion;
- if (trueTb == LongBinding || trueTb == DoubleBinding) {
+
+ public TypeBinding resolveType(BlockScope scope) {
+ // specs p.368
+ constant = NotAConstant;
+ TypeBinding conditionType = condition.resolveTypeExpecting(scope, BooleanBinding);
+ TypeBinding valueIfTrueType = valueIfTrue.resolveType(scope);
+ TypeBinding valueIfFalseType = valueIfFalse.resolveType(scope);
+ if (conditionType == null || valueIfTrueType == null || valueIfFalseType == null)
+ return null;
+
+ // Propagate the constant value from the valueIfTrue and valueIFFalse expression if it is possible
+ if (condition.constant != NotAConstant
+ && valueIfTrue.constant != NotAConstant
+ && valueIfFalse.constant != NotAConstant) {
+ // all terms are constant expression so we can propagate the constant
+ // from valueIFTrue or valueIfFalse to teh receiver constant
+ constant =
+ (condition.constant.booleanValue())
+ ? valueIfTrue.constant
+ : valueIfFalse.constant;
+ }
+ if (valueIfTrueType == valueIfFalseType) { // harmed the implicit conversion
+ valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
+ valueIfFalse.implicitConversion = valueIfTrue.implicitConversion;
+ if (valueIfTrueType == LongBinding || valueIfTrueType == DoubleBinding) {
+ returnTypeSlotSize = 2;
+ }
+ return valueIfTrueType;
+ }
+ // Determine the return type depending on argument types
+ // Numeric types
+ if (valueIfTrueType.isNumericType() && valueIfFalseType.isNumericType()) {
+ // (Short x Byte) or (Byte x Short)"
+ if ((valueIfTrueType == ByteBinding && valueIfFalseType == ShortBinding)
+ || (valueIfTrueType == ShortBinding && valueIfFalseType == ByteBinding)) {
+ valueIfTrue.implicitWidening(ShortBinding, valueIfTrueType);
+ valueIfFalse.implicitWidening(ShortBinding, valueIfFalseType);
+ return ShortBinding;
+ }
+ // <Byte|Short|Char> x constant(Int) ---> <Byte|Short|Char> and reciprocally
+ if ((valueIfTrueType == ByteBinding || valueIfTrueType == ShortBinding || valueIfTrueType == CharBinding)
+ && (valueIfFalseType == IntBinding
+ && valueIfFalse.isConstantValueOfTypeAssignableToType(valueIfFalseType, valueIfTrueType))) {
+ valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
+ valueIfFalse.implicitWidening(valueIfTrueType, valueIfFalseType);
+ return valueIfTrueType;
+ }
+ if ((valueIfFalseType == ByteBinding
+ || valueIfFalseType == ShortBinding
+ || valueIfFalseType == CharBinding)
+ && (valueIfTrueType == IntBinding
+ && valueIfTrue.isConstantValueOfTypeAssignableToType(valueIfTrueType, valueIfFalseType))) {
+ valueIfTrue.implicitWidening(valueIfFalseType, valueIfTrueType);
+ valueIfFalse.implicitWidening(valueIfFalseType, valueIfFalseType);
+ return valueIfFalseType;
+ }
+ // Manual binary numeric promotion
+ // int
+ if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_int)
+ && BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_int)) {
+ valueIfTrue.implicitWidening(IntBinding, valueIfTrueType);
+ valueIfFalse.implicitWidening(IntBinding, valueIfFalseType);
+ return IntBinding;
+ }
+ // long
+ if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_long)
+ && BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_long)) {
+ valueIfTrue.implicitWidening(LongBinding, valueIfTrueType);
+ valueIfFalse.implicitWidening(LongBinding, valueIfFalseType);
+ returnTypeSlotSize = 2;
+ return LongBinding;
+ }
+ // float
+ if (BaseTypeBinding.isNarrowing(valueIfTrueType.id, T_float)
+ && BaseTypeBinding.isNarrowing(valueIfFalseType.id, T_float)) {
+ valueIfTrue.implicitWidening(FloatBinding, valueIfTrueType);
+ valueIfFalse.implicitWidening(FloatBinding, valueIfFalseType);
+ return FloatBinding;
+ }
+ // double
+ valueIfTrue.implicitWidening(DoubleBinding, valueIfTrueType);
+ valueIfFalse.implicitWidening(DoubleBinding, valueIfFalseType);
returnTypeSlotSize = 2;
+ return DoubleBinding;
}
- return trueTb;
- }
-
- // Determine the return type depending on argument types
- // Numeric types
- if (trueTb.isNumericType() && falseTb.isNumericType()) {
- // (Short x Byte) or (Byte x Short)"
- if ((trueTb == ByteBinding && falseTb == ShortBinding) || (trueTb == ShortBinding && falseTb == ByteBinding)) {
- valueIfTrue.implicitWidening(ShortBinding, trueTb);
- valueIfFalse.implicitWidening(ShortBinding, falseTb);
- return ShortBinding;
+ // Type references (null null is already tested)
+ if ((valueIfTrueType.isBaseType() && valueIfTrueType != NullBinding)
+ || (valueIfFalseType.isBaseType() && valueIfFalseType != NullBinding)) {
+ scope.problemReporter().conditionalArgumentsIncompatibleTypes(
+ this,
+ valueIfTrueType,
+ valueIfFalseType);
+ return null;
}
-
- // <Byte|Short|Char> x constant(Int) ---> <Byte|Short|Char> and reciprocally
- if ((trueTb == ByteBinding || trueTb == ShortBinding || trueTb == CharBinding) &&
- (falseTb == IntBinding && valueIfFalse.isConstantValueOfTypeAssignableToType(falseTb, trueTb))) {
- valueIfTrue.implicitWidening(trueTb, trueTb);
- valueIfFalse.implicitWidening(trueTb, falseTb);
- return trueTb;
+ if (scope.areTypesCompatible(valueIfFalseType, valueIfTrueType)) {
+ valueIfTrue.implicitWidening(valueIfTrueType, valueIfTrueType);
+ valueIfFalse.implicitWidening(valueIfTrueType, valueIfFalseType);
+ return valueIfTrueType;
}
- if ((falseTb == ByteBinding || falseTb == ShortBinding || falseTb == CharBinding) &&
- (trueTb == IntBinding && valueIfTrue.isConstantValueOfTypeAssignableToType(trueTb, falseTb))) {
- valueIfTrue.implicitWidening(falseTb, trueTb);
- valueIfFalse.implicitWidening(falseTb, falseTb);
- return falseTb;
+ if (scope.areTypesCompatible(valueIfTrueType, valueIfFalseType)) {
+ valueIfTrue.implicitWidening(valueIfFalseType, valueIfTrueType);
+ valueIfFalse.implicitWidening(valueIfFalseType, valueIfFalseType);
+ return valueIfFalseType;
}
-
- // Manual binary numeric promotion
- // int
- if (BaseTypeBinding.isNarrowing(trueTb.id, T_int) && BaseTypeBinding.isNarrowing(falseTb.id, T_int)) {
- valueIfTrue.implicitWidening(IntBinding, trueTb);
- valueIfFalse.implicitWidening(IntBinding, falseTb);
- return IntBinding;
- }
- // long
- if (BaseTypeBinding.isNarrowing(trueTb.id, T_long) && BaseTypeBinding.isNarrowing(falseTb.id, T_long)) {
- valueIfTrue.implicitWidening(LongBinding, trueTb);
- valueIfFalse.implicitWidening(LongBinding, falseTb);
- returnTypeSlotSize = 2;
- return LongBinding;
- }
- // float
- if (BaseTypeBinding.isNarrowing(trueTb.id, T_float) && BaseTypeBinding.isNarrowing(falseTb.id, T_float)) {
- valueIfTrue.implicitWidening(FloatBinding, trueTb);
- valueIfFalse.implicitWidening(FloatBinding, falseTb);
- return FloatBinding;
- }
- // double
- valueIfTrue.implicitWidening(DoubleBinding, trueTb);
- valueIfFalse.implicitWidening(DoubleBinding, falseTb);
- returnTypeSlotSize = 2;
- return DoubleBinding;
- }
-
- // Type references (null null is already tested)
- if ((trueTb.isBaseType() && trueTb != NullBinding) || (falseTb.isBaseType() && falseTb != NullBinding)) {
- scope.problemReporter().conditionalArgumentsIncompatibleTypes(this, trueTb, falseTb);
+ scope.problemReporter().conditionalArgumentsIncompatibleTypes(
+ this,
+ valueIfTrueType,
+ valueIfFalseType);
return null;
}
- if (scope.areTypesCompatible(falseTb, trueTb)) {
- valueIfTrue.implicitWidening(trueTb, trueTb);
- valueIfFalse.implicitWidening(trueTb, falseTb);
- return trueTb;
+
+ public String toStringExpressionNoParenthesis() {
+ return condition.toStringExpression() + " ? " + //$NON-NLS-1$
+ valueIfTrue.toStringExpression() + " : " + //$NON-NLS-1$
+ valueIfFalse.toStringExpression();
}
- if (scope.areTypesCompatible(trueTb, falseTb)) {
- valueIfTrue.implicitWidening(falseTb, trueTb);
- valueIfFalse.implicitWidening(falseTb, falseTb);
- return falseTb;
- }
- scope.problemReporter().conditionalArgumentsIncompatibleTypes(this, trueTb, falseTb);
- return null;
-}
-public String toStringExpressionNoParenthesis(){
- /* slow code*/
- return condition.toStringExpression() + " ? " + //$NON-NLS-1$
- valueIfTrue.toStringExpression() + " : " + //$NON-NLS-1$
- valueIfFalse.toStringExpression() ; }
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
- if (visitor.visit(this, scope)) {
- condition.traverse(visitor, scope);
- valueIfTrue.traverse(visitor, scope);
- valueIfFalse.traverse(visitor, scope);
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ condition.traverse(visitor, scope);
+ valueIfTrue.traverse(visitor, scope);
+ valueIfFalse.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
}
- visitor.endVisit(this, scope);
-}
-}
+}
\ No newline at end of file
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
index 027cc07..978ba12 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/EqualExpression.java
@@ -247,32 +247,11 @@
* Optimized operations are: == and !=
*/
public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
- int pc = codeStream.position;
if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
- if (constant.booleanValue() == true) {
- // constant == true
- if (valueRequired) {
- if (falseLabel == null) {
- // implicit falling through the FALSE case
- if (trueLabel != null) {
- codeStream.goto_(trueLabel);
- }
- }
- }
- } else {
- // constant == false
- if (valueRequired) {
- if (falseLabel != null) {
- // implicit falling through the TRUE case
- if (trueLabel == null) {
- codeStream.goto_(falseLabel);
- }
- }
- }
- }
- codeStream.recordPositionsFrom(pc, this);
+ super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
return;
}
+ int pc = codeStream.position;
if (((bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL) {
if ((left.implicitConversion & 0xF) /*compile-time*/ == T_boolean) {
generateOptimizedBooleanEqual(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
index d46f5a7..cc1bb77 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/OR_OR_Expression.java
@@ -10,263 +10,281 @@
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
+//dedicated treatment for the ||
public class OR_OR_Expression extends BinaryExpression {
- //dedicated treatment for the &&
+
int rightInitStateIndex = -1;
int mergedInitStateIndex = -1;
-public OR_OR_Expression(Expression left, Expression right,int operator) {
- super(left,right,operator);
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
+ public OR_OR_Expression(Expression left, Expression right, int operator) {
+ super(left, right, operator);
+ }
- Constant opConstant;
- if ((opConstant = left.constant) != NotAConstant) {
- if (opConstant.booleanValue() == false) {
- // FALSE || anything
- return right.analyseCode(currentScope, flowContext, flowInfo);
- } else {
- // TRUE || anything
- return flowInfo;
- }
- }
- if ((opConstant = right.constant) != NotAConstant) {
- if (opConstant.booleanValue() == true) {
- // anything || TRUE
- // whatever is on the left, we will succeed, so the result must merge the left inits when answering
- // initsWhenTrue.
- // the initsWhenFalse are undetermined, since this path will be fake reachable...
- FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
- return mergedInfo;
- } else {
- // anything || FALSE
- // ignore the right part
- FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo);
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
- return mergedInfo;
- }
- }
- if ((opConstant = left.conditionalConstant()) != NotAConstant) {
- if (opConstant.booleanValue() == true){
- // TRUE || anything
- FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo);
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
- right.analyseCode(currentScope, flowContext, mergedInfo.copy().markAsFakeReachable(true));
- return mergedInfo;
- }
- }
- FlowInfo leftInfo, rightInfo; leftInfo = left.analyseCode(currentScope, flowContext, flowInfo);
- rightInfo = leftInfo.initsWhenFalse().copy();
- rightInitStateIndex = currentScope.methodScope().recordInitializationStates(rightInfo);
- rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
- FlowInfo mergedInfo = FlowInfo.conditional(
- // merging two true initInfos for such a negative case: if ((t && (b = t)) || f) r = b; // b may not have been initialized
- leftInfo.initsWhenTrue().unconditionalInits().mergedWith(rightInfo.initsWhenTrue().copy().unconditionalInits()),
- rightInfo.initsWhenFalse());
- mergedInitStateIndex = currentScope.methodScope().recordInitializationStates(mergedInfo);
- return mergedInfo;
-}
-public void computeConstant(BlockScope scope, int leftId, int rightId) {
- //the TC has been done so leftId and rightId are both equal to T_boolean
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
- Constant cst;
- if ((cst = left.constant) != NotAConstant) {
- if (cst.booleanValue() == true) { // true || x --> true
- constant = cst; // inlined to constant(false)
- } else { // false || x --> x
- if ((constant = right.constant) == NotAConstant) {
- // compute conditionalConstant
- optimizedBooleanConstant(leftId, (bits & OperatorMASK) >> OperatorSHIFT, rightId);
+ Constant opConstant = left.conditionalConstant();
+ if (opConstant != NotAConstant) {
+ if (opConstant.booleanValue() == false) {
+ // FALSE || anything
+ // need to be careful of scenario:
+ // (x || y) || !z, if passing the left info to the right, it would be swapped by the !
+ FlowInfo mergedInfo = left.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
+ mergedInfo = right.analyseCode(currentScope, flowContext, mergedInfo);
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergedInfo);
+ return mergedInfo;
}
}
- } else {
- constant = NotAConstant;
- // compute conditionalConstant
- optimizedBooleanConstant(leftId, (bits & OperatorMASK) >> OperatorSHIFT, rightId);
+ FlowInfo leftInfo, rightInfo;
+ leftInfo = left.analyseCode(currentScope, flowContext, flowInfo);
+
+ // need to be careful of scenario:
+ // (x || y) || !z, if passing the left info to the right, it would be swapped by the !
+ rightInfo = leftInfo.initsWhenFalse().unconditionalInits().copy();
+ if (opConstant != NotAConstant && opConstant.booleanValue() == true) rightInfo.markAsFakeReachable(true);
+
+ rightInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(rightInfo);
+ rightInfo = right.analyseCode(currentScope, flowContext, rightInfo);
+ FlowInfo mergedInfo = FlowInfo.conditional(
+ // merging two true initInfos for such a negative case: if ((t && (b = t)) || f) r = b; // b may not have been initialized
+ leftInfo.initsWhenTrue().copy().unconditionalInits().mergedWith(
+ rightInfo.initsWhenTrue().copy().unconditionalInits()),
+ rightInfo.initsWhenFalse().copy());
+ mergedInitStateIndex =
+ currentScope.methodScope().recordInitializationStates(mergedInfo);
+ return mergedInfo;
}
-}
-/**
- * Code generation for a binary operation
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param valueRequired boolean
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
- int pc = codeStream.position;
- Label falseLabel, endLabel;
- if (constant != Constant.NotAConstant) {
- if (valueRequired)
- codeStream.generateConstant(constant, implicitConversion);
- codeStream.recordPositionsFrom(pc, this);
- return;
- }
- bits |= OnlyValueRequiredMASK;
- generateOptimizedConditionalOr(currentScope, codeStream, null, (falseLabel = new Label(codeStream)), valueRequired);
- /* improving code gen for such a case: boolean b = i < 0 || true;
- * since the label has never been used, we have the inlined value on the stack. */
- if (falseLabel.hasForwardReferences()) {
- if (valueRequired) {
- codeStream.iconst_1();
- if ((bits & ValueForReturnMASK) != 0) {
- codeStream.ireturn();
- falseLabel.place();
- codeStream.iconst_0();
- } else {
- codeStream.goto_(endLabel = new Label(codeStream));
- codeStream.decrStackSize(1);
- falseLabel.place();
- codeStream.iconst_0();
- endLabel.place();
- }
- } else {
- falseLabel.place();
- }
- }
- if (valueRequired) {
- codeStream.generateImplicitConversion(implicitConversion);
- }
- codeStream.recordPositionsFrom(pc, this);
-}
-/**
- * Boolean operator code generation
- * Optimized operations are: ||
- */
-public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
- if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
+
+ /**
+ * Code generation for a binary operation
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+ public void generateCode(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ boolean valueRequired) {
int pc = codeStream.position;
- if (constant.booleanValue() == true) {
- // constant == true
- if (valueRequired) {
- if (falseLabel == null) {
- // implicit falling through the FALSE case
- if (trueLabel != null) {
- codeStream.goto_(trueLabel);
- }
- }
- }
- } else {
- if (valueRequired) {
- if (falseLabel != null) {
- // implicit falling through the TRUE case
- if (trueLabel == null) {
- codeStream.goto_(falseLabel);
- }
- }
- }
+ Label falseLabel, endLabel;
+ if (constant != Constant.NotAConstant) {
+ if (valueRequired)
+ codeStream.generateConstant(constant, implicitConversion);
+ codeStream.recordPositionsFrom(pc, this);
+ return;
}
- codeStream.recordPositionsFrom(pc, this);
- return;
- }
- generateOptimizedConditionalOr(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
-}
-/**
- * Boolean generation for ||
- */
-public void generateOptimizedConditionalOr(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
- int pc = codeStream.position;
- Constant condConst;
- if ((condConst = left.conditionalConstant()) != NotAConstant) {
- if (condConst.booleanValue() == true) {
- // <something equivalent to true> || x
- left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, false);
+ bits |= OnlyValueRequiredMASK;
+ generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ (falseLabel = new Label(codeStream)),
+ valueRequired);
+ /* improving code gen for such a case: boolean b = i < 0 || true;
+ * since the label has never been used, we have the inlined value on the stack. */
+ if (falseLabel.hasForwardReferences()) {
if (valueRequired) {
- if ((bits & OnlyValueRequiredMASK) != 0) {
- codeStream.iconst_1();
+ codeStream.iconst_1();
+ if ((bits & ValueForReturnMASK) != 0) {
+ codeStream.ireturn();
+ falseLabel.place();
+ codeStream.iconst_0();
} else {
- if (trueLabel != null) {
- codeStream.goto_(trueLabel);
- }
+ codeStream.goto_(endLabel = new Label(codeStream));
+ codeStream.decrStackSize(1);
+ falseLabel.place();
+ codeStream.iconst_0();
+ endLabel.place();
}
- }
- } else {
- // <something equivalent to false> || x
- left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, false);
- if (rightInitStateIndex != -1){
- codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
- }
- if ((bits & OnlyValueRequiredMASK) != 0){
- right.generateCode(currentScope, codeStream, valueRequired);
} else {
- right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+ falseLabel.place();
}
}
+ if (valueRequired) {
+ codeStream.generateImplicitConversion(implicitConversion);
+ }
codeStream.recordPositionsFrom(pc, this);
- if (mergedInitStateIndex != -1){
- codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
- }
- return;
}
- if ((condConst = right.conditionalConstant()) != NotAConstant) {
- if (condConst.booleanValue() == true) {
- // x || <something equivalent to true>
- left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, false);
- if (rightInitStateIndex != -1){
- codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
- }
- right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, false);
- if (valueRequired) {
+
+ /**
+ * Boolean operator code generation
+ * Optimized operations are: ||
+ */
+ public void generateOptimizedBoolean(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ Label trueLabel,
+ Label falseLabel,
+ boolean valueRequired) {
+ if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
+ super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+ return;
+ }
+ int pc = codeStream.position;
+ Constant condConst;
+ if ((condConst = left.conditionalConstant()) != NotAConstant) {
+ if (condConst.booleanValue() == true) {
+ // <something equivalent to true> || x
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (valueRequired) {
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ codeStream.iconst_1();
+ } else {
+ if (trueLabel != null) {
+ codeStream.goto_(trueLabel);
+ }
+ }
+ }
+ } else {
+ // <something equivalent to false> || x
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
if ((bits & OnlyValueRequiredMASK) != 0) {
- codeStream.iconst_1();
+ right.generateCode(currentScope, codeStream, valueRequired);
} else {
- if (trueLabel != null) {
- codeStream.goto_(trueLabel);
- }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ valueRequired);
}
}
- } else {
- // x || <something equivalent to false>
- if ((bits & OnlyValueRequiredMASK) != 0){
- left.generateCode(currentScope, codeStream, valueRequired);
+ codeStream.recordPositionsFrom(pc, this);
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
+ }
+ return;
+ }
+ if ((condConst = right.conditionalConstant()) != NotAConstant) {
+ if (condConst.booleanValue() == true) {
+ // x || <something equivalent to true>
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
+ if (valueRequired) {
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ codeStream.iconst_1();
+ } else {
+ if (trueLabel != null) {
+ codeStream.goto_(trueLabel);
+ }
+ }
+ }
} else {
- left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
+ // x || <something equivalent to false>
+ if ((bits & OnlyValueRequiredMASK) != 0) {
+ left.generateCode(currentScope, codeStream, valueRequired);
+ } else {
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ valueRequired);
+ }
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ false);
}
- if (rightInitStateIndex != -1){
- codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ codeStream.recordPositionsFrom(pc, this);
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
}
- right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, false);
+ return;
+ }
+ // default case
+ if (falseLabel == null) {
+ if (trueLabel != null) {
+ // implicit falling through the FALSE case
+ left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, true);
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ null,
+ valueRequired);
+ }
+ } else {
+ // implicit falling through the TRUE case
+ if (trueLabel == null) {
+ Label internalTrueLabel = new Label(codeStream);
+ left.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ internalTrueLabel,
+ null,
+ true);
+ if (rightInitStateIndex != -1) {
+ codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
+ }
+ right.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ falseLabel,
+ valueRequired);
+ internalTrueLabel.place();
+ } else {
+ // no implicit fall through TRUE/FALSE --> should never occur
+ }
}
codeStream.recordPositionsFrom(pc, this);
- if (mergedInitStateIndex != -1){
- codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
- }
- return;
- }
- // default case
- if (falseLabel == null) {
- if (trueLabel != null) {
- // implicit falling through the FALSE case
- left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, true);
- right.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, valueRequired);
- }
- } else {
- // implicit falling through the TRUE case
- if (trueLabel == null) {
- Label internalTrueLabel = new Label(codeStream);
- left.generateOptimizedBoolean(currentScope, codeStream, internalTrueLabel, null, true);
- if (rightInitStateIndex != -1){
- codeStream.addDefinitelyAssignedVariables(currentScope, rightInitStateIndex);
- }
- right.generateOptimizedBoolean(currentScope, codeStream, null, falseLabel, valueRequired);
- internalTrueLabel.place();
- } else {
- // no implicit fall through TRUE/FALSE --> should never occur
+ if (mergedInitStateIndex != -1) {
+ codeStream.removeNotDefinitelyAssignedVariables(
+ currentScope,
+ mergedInitStateIndex);
}
}
- codeStream.recordPositionsFrom(pc, this);
- if (mergedInitStateIndex != -1){
- codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
+
+ public boolean isCompactableOperation() {
+ return false;
}
-}
-public boolean isCompactableOperation() {
- return false;
-}
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
- if (visitor.visit(this, scope)) {
- left.traverse(visitor, scope);
- right.traverse(visitor, scope);
+
+ public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope scope) {
+ if (visitor.visit(this, scope)) {
+ left.traverse(visitor, scope);
+ right.traverse(visitor, scope);
+ }
+ visitor.endVisit(this, scope);
}
- visitor.endVisit(this, scope);
-}
-}
+}
\ No newline at end of file
diff --git a/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java b/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
index 3093dd5..6d0f336 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/ast/UnaryExpression.java
@@ -10,246 +10,270 @@
import org.eclipse.jdt.internal.compiler.flow.*;
import org.eclipse.jdt.internal.compiler.lookup.*;
-
public class UnaryExpression extends OperatorExpression {
+
public Expression expression;
public Constant optimizedBooleanConstant;
-public UnaryExpression(Expression expression, int operator) {
- this.expression = expression;
- this.bits |= operator << OperatorSHIFT; // encode operator
-}
-public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
- if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
- return expression.analyseCode(currentScope, flowContext, flowInfo).asNegatedCondition();
- } else {
- return expression.analyseCode(currentScope, flowContext, flowInfo);
- }
-}
-public Constant conditionalConstant(){
-
- return optimizedBooleanConstant == null ?
- constant :
- optimizedBooleanConstant ;}
-/**
- * Code generation for an unary operation
- *
- * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
- * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
- * @param valueRequired boolean
- */
-public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
- int pc = codeStream.position;
- Label falseLabel, endifLabel;
- if (constant != Constant.NotAConstant) {
- // inlined value
- if (valueRequired){
- codeStream.generateConstant(constant, implicitConversion);
- }
- codeStream.recordPositionsFrom(pc, this);
- return;
- }
- switch ((bits & OperatorMASK) >> OperatorSHIFT) {
- case NOT :
- switch (expression.implicitConversion >> 4 )/* runtime type */ {
- case T_boolean :
- // ! <boolean>
- // Generate code for the condition
- expression.generateOptimizedBoolean(currentScope, codeStream, null, (falseLabel = new Label(codeStream)), valueRequired);
- if (valueRequired) {
- codeStream.iconst_0();
- codeStream.goto_(endifLabel = new Label(codeStream));
- codeStream.decrStackSize(1);
- falseLabel.place();
- if (valueRequired)
- codeStream.iconst_1();
- endifLabel.place();
- }
- break;
- }
- break;
- case TWIDDLE :
- switch (expression.implicitConversion >> 4 /* runtime */) {
- case T_int :
- // ~int
- expression.generateCode(currentScope, codeStream, valueRequired);
- if (valueRequired) {
- codeStream.iconst_m1();
- codeStream.ixor();
- }
- break;
- case T_long :
- expression.generateCode(currentScope, codeStream, valueRequired);
- if (valueRequired) {
- codeStream.ldc2_w(-1L);
- codeStream.lxor();
- }
- }
- break;
- case MINUS :
- // - <num>
- if (constant != NotAConstant) {
- if (valueRequired) {
- switch (expression.implicitConversion >> 4 /* runtime */) {
- case T_int :
- codeStream.generateInlinedValue(constant.intValue() * -1);
- break;
- case T_float :
- codeStream.generateInlinedValue(constant.floatValue() * -1.0f);
- break;
- case T_long :
- codeStream.generateInlinedValue(constant.longValue() * -1L);
- break;
- case T_double :
- codeStream.generateInlinedValue(constant.doubleValue() * -1.0);
- }
- }
- } else {
- expression.generateCode(currentScope, codeStream, valueRequired);
- if (valueRequired) {
- switch (expression.implicitConversion >> 4 /* runtime type */) {
- case T_int :
- codeStream.ineg();
- break;
- case T_float :
- codeStream.fneg();
- break;
- case T_long :
- codeStream.lneg();
- break;
- case T_double :
- codeStream.dneg();
- }
- }
- }
- break;
- case PLUS :
- expression.generateCode(currentScope, codeStream, valueRequired);
- }
- if (valueRequired) {
- codeStream.generateImplicitConversion(implicitConversion);
- }
- codeStream.recordPositionsFrom(pc, this);
-}
-/**
- * Boolean operator code generation
- * Optimized operations are: &&, ||, <, <=, >, >=, &, |, ^
- */
-public void generateOptimizedBoolean(BlockScope currentScope, CodeStream codeStream, Label trueLabel, Label falseLabel, boolean valueRequired) {
-
- if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
- int pc = codeStream.position;
- if (constant.booleanValue() == true) {
- // constant == true
- if (valueRequired) {
- if (falseLabel == null) {
- // implicit falling through the FALSE case
- if (trueLabel != null) {
- codeStream.goto_(trueLabel);
- }
- }
- }
- } else {
- if (valueRequired) {
- if (falseLabel != null) {
- // implicit falling through the TRUE case
- if (trueLabel == null) {
- codeStream.goto_(falseLabel);
- }
- }
- }
- }
- codeStream.recordPositionsFrom(pc, this);
- return;
- }
- if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
- expression.generateOptimizedBoolean(currentScope, codeStream, falseLabel, trueLabel, valueRequired);
- } else {
- super.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel, valueRequired);
- }
-}
-public TypeBinding resolveType(BlockScope scope) {
- TypeBinding expressionTb = expression.resolveType(scope);
- if (expressionTb == null){
- constant = NotAConstant;
- return null;
- }
- int expressionId = expressionTb.id;
- if (expressionId > 15) {
- constant = NotAConstant;
- scope.problemReporter().invalidOperator(this, expressionTb);
- return null;
+ public UnaryExpression(Expression expression, int operator) {
+ this.expression = expression;
+ this.bits |= operator << OperatorSHIFT; // encode operator
}
- int tableId;
- switch ((bits & OperatorMASK) >> OperatorSHIFT) {
- case NOT :
- tableId = AND_AND;
- break;
- case TWIDDLE :
- tableId = LEFT_SHIFT;
- break;
- default :
- tableId = MINUS;
- } //+ and - cases
-
- // the code is an int
- // (cast) left Op (cast) rigth --> result
- // 0000 0000 0000 0000 0000
- // <<16 <<12 <<8 <<4 <<0
- int result = ResolveTypeTables[tableId][(expressionId << 4) + expressionId];
- expression.implicitConversion = result >>> 12;
- TypeBinding type;
- switch (result & 0x0000F) { // only switch on possible result type.....
- case T_boolean :
- type = BooleanBinding;
- break;
- case T_byte :
- type = ByteBinding;
- break;
- case T_char :
- type = CharBinding;
- break;
- case T_double :
- type = DoubleBinding;
- break;
- case T_float :
- type = FloatBinding;
- break;
- case T_int :
- type = IntBinding;
- break;
- case T_long :
- type = LongBinding;
- break;
- default : //error........
- constant = Constant.NotAConstant;
- if (expressionId != T_undefined)
- scope.problemReporter().invalidOperator(this, expressionTb);
- return null;
- }
-
- // compute the constant when valid
- if (expression.constant != Constant.NotAConstant) {
- constant = Constant.computeConstantOperation(expression.constant, expressionId, (bits & OperatorMASK) >> OperatorSHIFT);
- } else {
- constant = Constant.NotAConstant;
+ public FlowInfo analyseCode(
+ BlockScope currentScope,
+ FlowContext flowContext,
+ FlowInfo flowInfo) {
if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
- Constant cst = expression.conditionalConstant();
- if (cst.typeID() == T_boolean)
- optimizedBooleanConstant = Constant.fromValue(!cst.booleanValue());
+ return expression
+ .analyseCode(currentScope, flowContext, flowInfo)
+ .asNegatedCondition();
+ } else {
+ return expression.analyseCode(currentScope, flowContext, flowInfo);
}
}
- return type;
-}
-public String toStringExpressionNoParenthesis(){
- /* slow code*/
- return operatorToString() + " " + expression.toStringExpression() ; } //$NON-NLS-1$
-public void traverse(IAbstractSyntaxTreeVisitor visitor, BlockScope blockScope) {
- if (visitor.visit(this, blockScope)) {
- expression.traverse(visitor, blockScope);
+ public Constant conditionalConstant() {
+ return optimizedBooleanConstant == null ? constant : optimizedBooleanConstant;
}
- visitor.endVisit(this, blockScope);
-}
-}
+
+ /**
+ * Code generation for an unary operation
+ *
+ * @param currentScope org.eclipse.jdt.internal.compiler.lookup.BlockScope
+ * @param codeStream org.eclipse.jdt.internal.compiler.codegen.CodeStream
+ * @param valueRequired boolean
+ */
+ public void generateCode(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ boolean valueRequired) {
+ int pc = codeStream.position;
+ Label falseLabel, endifLabel;
+ if (constant != Constant.NotAConstant) {
+ // inlined value
+ if (valueRequired) {
+ codeStream.generateConstant(constant, implicitConversion);
+ }
+ codeStream.recordPositionsFrom(pc, this);
+ return;
+ }
+ switch ((bits & OperatorMASK) >> OperatorSHIFT) {
+ case NOT :
+ switch (expression.implicitConversion >> 4) /* runtime type */ {
+ case T_boolean :
+ // ! <boolean>
+ // Generate code for the condition
+ expression.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ null,
+ (falseLabel = new Label(codeStream)),
+ valueRequired);
+ if (valueRequired) {
+ codeStream.iconst_0();
+ codeStream.goto_(endifLabel = new Label(codeStream));
+ codeStream.decrStackSize(1);
+ falseLabel.place();
+ if (valueRequired)
+ codeStream.iconst_1();
+ endifLabel.place();
+ }
+ break;
+ }
+ break;
+ case TWIDDLE :
+ switch (expression.implicitConversion >> 4 /* runtime */
+ ) {
+ case T_int :
+ // ~int
+ expression.generateCode(currentScope, codeStream, valueRequired);
+ if (valueRequired) {
+ codeStream.iconst_m1();
+ codeStream.ixor();
+ }
+ break;
+ case T_long :
+ expression.generateCode(currentScope, codeStream, valueRequired);
+ if (valueRequired) {
+ codeStream.ldc2_w(-1L);
+ codeStream.lxor();
+ }
+ }
+ break;
+ case MINUS :
+ // - <num>
+ if (constant != NotAConstant) {
+ if (valueRequired) {
+ switch (expression.implicitConversion >> 4 /* runtime */
+ ) {
+ case T_int :
+ codeStream.generateInlinedValue(constant.intValue() * -1);
+ break;
+ case T_float :
+ codeStream.generateInlinedValue(constant.floatValue() * -1.0f);
+ break;
+ case T_long :
+ codeStream.generateInlinedValue(constant.longValue() * -1L);
+ break;
+ case T_double :
+ codeStream.generateInlinedValue(constant.doubleValue() * -1.0);
+ }
+ }
+ } else {
+ expression.generateCode(currentScope, codeStream, valueRequired);
+ if (valueRequired) {
+ switch (expression.implicitConversion >> 4 /* runtime type */
+ ) {
+ case T_int :
+ codeStream.ineg();
+ break;
+ case T_float :
+ codeStream.fneg();
+ break;
+ case T_long :
+ codeStream.lneg();
+ break;
+ case T_double :
+ codeStream.dneg();
+ }
+ }
+ }
+ break;
+ case PLUS :
+ expression.generateCode(currentScope, codeStream, valueRequired);
+ }
+ if (valueRequired) {
+ codeStream.generateImplicitConversion(implicitConversion);
+ }
+ codeStream.recordPositionsFrom(pc, this);
+ }
+
+ /**
+ * Boolean operator code generation
+ * Optimized operations are: &&, ||, <, <=, >, >=, &, |, ^
+ */
+ public void generateOptimizedBoolean(
+ BlockScope currentScope,
+ CodeStream codeStream,
+ Label trueLabel,
+ Label falseLabel,
+ boolean valueRequired) {
+
+ if ((constant != Constant.NotAConstant) && (constant.typeID() == T_boolean)) {
+ super.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ valueRequired);
+ return;
+ }
+ if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
+ expression.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ falseLabel,
+ trueLabel,
+ valueRequired);
+ } else {
+ super.generateOptimizedBoolean(
+ currentScope,
+ codeStream,
+ trueLabel,
+ falseLabel,
+ valueRequired);
+ }
+ }
+
+ public TypeBinding resolveType(BlockScope scope) {
+ TypeBinding expressionTb = expression.resolveType(scope);
+ if (expressionTb == null) {
+ constant = NotAConstant;
+ return null;
+ }
+ int expressionId = expressionTb.id;
+ if (expressionId > 15) {
+ constant = NotAConstant;
+ scope.problemReporter().invalidOperator(this, expressionTb);
+ return null;
+ }
+
+ int tableId;
+ switch ((bits & OperatorMASK) >> OperatorSHIFT) {
+ case NOT :
+ tableId = AND_AND;
+ break;
+ case TWIDDLE :
+ tableId = LEFT_SHIFT;
+ break;
+ default :
+ tableId = MINUS;
+ } //+ and - cases
+
+ // the code is an int
+ // (cast) left Op (cast) rigth --> result
+ // 0000 0000 0000 0000 0000
+ // <<16 <<12 <<8 <<4 <<0
+ int result = ResolveTypeTables[tableId][(expressionId << 4) + expressionId];
+ expression.implicitConversion = result >>> 12;
+ TypeBinding type;
+ switch (result & 0x0000F) { // only switch on possible result type.....
+ case T_boolean :
+ type = BooleanBinding;
+ break;
+ case T_byte :
+ type = ByteBinding;
+ break;
+ case T_char :
+ type = CharBinding;
+ break;
+ case T_double :
+ type = DoubleBinding;
+ break;
+ case T_float :
+ type = FloatBinding;
+ break;
+ case T_int :
+ type = IntBinding;
+ break;
+ case T_long :
+ type = LongBinding;
+ break;
+ default : //error........
+ constant = Constant.NotAConstant;
+ if (expressionId != T_undefined)
+ scope.problemReporter().invalidOperator(this, expressionTb);
+ return null;
+ }
+ // compute the constant when valid
+ if (expression.constant != Constant.NotAConstant) {
+ constant =
+ Constant.computeConstantOperation(
+ expression.constant,
+ expressionId,
+ (bits & OperatorMASK) >> OperatorSHIFT);
+ } else {
+ constant = Constant.NotAConstant;
+ if (((bits & OperatorMASK) >> OperatorSHIFT) == NOT) {
+ Constant cst = expression.conditionalConstant();
+ if (cst.typeID() == T_boolean)
+ optimizedBooleanConstant = Constant.fromValue(!cst.booleanValue());
+ }
+ }
+ return type;
+ }
+
+ public String toStringExpressionNoParenthesis() {
+ return operatorToString() + " " + expression.toStringExpression(); //$NON-NLS-1$
+ }
+
+ public void traverse(
+ IAbstractSyntaxTreeVisitor visitor,
+ BlockScope blockScope) {
+ if (visitor.visit(this, blockScope)) {
+ expression.traverse(visitor, blockScope);
+ }
+ visitor.endVisit(this, blockScope);
+ }
+}
\ No newline at end of file
diff --git a/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java b/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
index 15dd6fe..929fd5e 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/flow/FlowInfo.java
@@ -21,6 +21,7 @@
return false;
}
public static FlowInfo conditional(FlowInfo initsWhenTrue, FlowInfo initsWhenFalse){
+ // if (initsWhenTrue.equals(initsWhenFalse)) return initsWhenTrue; -- could optimize if #equals is defined
return new ConditionalFlowInfo(initsWhenTrue, initsWhenFalse);
}
abstract public FlowInfo copy();
diff --git a/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java b/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
index be27e6c..447b8b5 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/flow/UnconditionalFlowInfo.java
@@ -233,7 +233,7 @@
*/
final public boolean isPotentiallyAssigned(FieldBinding field) {
// We do not want to complain in unreachable code
- if (this == DeadEnd)
+ if ((this == DeadEnd) || (this.isFakeReachable))
return false;
return isPotentiallyAssigned(field.id);
}
diff --git a/compiler/org/eclipse/jdt/internal/compiler/impl/Constant.java b/compiler/org/eclipse/jdt/internal/compiler/impl/Constant.java
index 8f05951..1237369 100644
--- a/compiler/org/eclipse/jdt/internal/compiler/impl/Constant.java
+++ b/compiler/org/eclipse/jdt/internal/compiler/impl/Constant.java
@@ -225,9 +225,9 @@
//the result should be availbale with not runtime error
switch (operator) {
- case NOT : if ( cst.booleanValue() == true ) return Constant.fromValue(false);
- return Constant.fromValue(true);
- case PLUS : return cst ; //apriori we do not need to clone it
+ case NOT :
+ return Constant.fromValue(!cst.booleanValue());
+ case PLUS : return cst ;
case MINUS : //the two special -9223372036854775808L and -2147483648 are inlined at parseTime
switch (id){
case T_float : float f ;