01: package gnu.expr;
02:
03: import gnu.bytecode.*;
04:
05: /** This is the Target of a boolean expression, in a conditional context.
06: * If the expression evaluates to, transfer to the ifTrue label;
07: * if false, tranfer to the ifFalse label. */
08:
09: public class ConditionalTarget extends Target {
10: public Label ifTrue, ifFalse;
11: Interpreter interpreter;
12:
13: /**
14: * @param ifTrue label to jump to if this evaluates to true
15: * @param ifFalse label to jump to if true
16: * @pram interpreter specifies what values are true
17: */
18:
19: public ConditionalTarget(Label ifTrue, Label ifFalse,
20: Interpreter interpreter) {
21: this .ifTrue = ifTrue;
22: this .ifFalse = ifFalse;
23: this .interpreter = interpreter;
24: }
25:
26: /** True if the ifTrue label comes before the ifFalse label.
27: * This is used in the hope we can optimize away a branch followed by
28: * its target. */
29: public boolean trueBranchComesFirst = true;
30:
31: public Type getType() {
32: return Type.boolean_type;
33: }
34:
35: public void compileFromStack(Compilation comp, Type stackType) {
36: CodeAttr code = comp.getCode();
37: char sig = stackType.getSignature().charAt(0);
38: switch (sig) {
39: case 'J':
40: code.emitPushLong(0);
41: break;
42: case 'D':
43: code.emitPushDouble(0.0);
44: break;
45: case 'F':
46: code.emitPushFloat(0.0f);
47: break;
48: default:
49: if (trueBranchComesFirst) {
50: code.emitGotoIfIntEqZero(ifFalse);
51: code.emitGoto(ifTrue);
52: } else {
53: code.emitGotoIfIntNeZero(ifTrue);
54: code.emitGoto(ifFalse);
55: }
56: return;
57: case 'L':
58: case '[':
59: comp.compileConstant(interpreter == null ? Boolean.FALSE
60: : interpreter.booleanObject(false));
61: break;
62: }
63: if (trueBranchComesFirst) {
64: code.emitGotoIfEq(ifFalse);
65: code.emitGoto(ifTrue);
66: } else {
67: code.emitGotoIfNE(ifTrue);
68: code.emitGoto(ifFalse);
69: }
70: }
71: }
|