コード例 #1
0
  /**
   * Boolean generation for == with boolean operands
   *
   * <p>Note this code does not optimize conditional constants !!!!
   */
  public void generateOptimizedBooleanEqual(
      BlockScope currentScope,
      CodeStream codeStream,
      BranchLabel trueLabel,
      BranchLabel falseLabel,
      boolean valueRequired) {

    // optimized cases: true == x, false == x
    if (this.left.constant != Constant.NotAConstant) {
      boolean inline = this.left.constant.booleanValue();
      this.right.generateOptimizedBoolean(
          currentScope,
          codeStream,
          (inline ? trueLabel : falseLabel),
          (inline ? falseLabel : trueLabel),
          valueRequired);
      return;
    } // optimized cases: x == true, x == false
    if (this.right.constant != Constant.NotAConstant) {
      boolean inline = this.right.constant.booleanValue();
      this.left.generateOptimizedBoolean(
          currentScope,
          codeStream,
          (inline ? trueLabel : falseLabel),
          (inline ? falseLabel : trueLabel),
          valueRequired);
      return;
    }
    // default case
    this.left.generateCode(currentScope, codeStream, valueRequired);
    this.right.generateCode(currentScope, codeStream, valueRequired);
    if (valueRequired) {
      if (falseLabel == null) {
        if (trueLabel != null) {
          // implicit falling through the FALSE case
          codeStream.if_icmpeq(trueLabel);
        }
      } else {
        // implicit falling through the TRUE case
        if (trueLabel == null) {
          codeStream.if_icmpne(falseLabel);
        } else {
          // no implicit fall through TRUE/FALSE --> should never occur
        }
      }
    }
    // reposition the endPC
    codeStream.updateLastRecordedEndPC(currentScope, codeStream.position);
  }
コード例 #2
0
  /** Boolean generation for == with non-boolean operands */
  public void generateOptimizedNonBooleanEqual(
      BlockScope currentScope,
      CodeStream codeStream,
      BranchLabel trueLabel,
      BranchLabel falseLabel,
      boolean valueRequired) {

    int pc = codeStream.position;
    Constant inline;
    if ((inline = this.right.constant) != Constant.NotAConstant) {
      // optimized case: x == 0
      if ((((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int)
          && (inline.intValue() == 0)) {
        this.left.generateCode(currentScope, codeStream, valueRequired);
        if (valueRequired) {
          if (falseLabel == null) {
            if (trueLabel != null) {
              // implicit falling through the FALSE case
              codeStream.ifeq(trueLabel);
            }
          } else {
            // implicit falling through the TRUE case
            if (trueLabel == null) {
              codeStream.ifne(falseLabel);
            } else {
              // no implicit fall through TRUE/FALSE --> should never occur
            }
          }
        }
        codeStream.recordPositionsFrom(pc, this.sourceStart);
        return;
      }
    }
    if ((inline = this.left.constant) != Constant.NotAConstant) {
      // optimized case: 0 == x
      if ((((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int)
          && (inline.intValue() == 0)) {
        this.right.generateCode(currentScope, codeStream, valueRequired);
        if (valueRequired) {
          if (falseLabel == null) {
            if (trueLabel != null) {
              // implicit falling through the FALSE case
              codeStream.ifeq(trueLabel);
            }
          } else {
            // implicit falling through the TRUE case
            if (trueLabel == null) {
              codeStream.ifne(falseLabel);
            } else {
              // no implicit fall through TRUE/FALSE --> should never occur
            }
          }
        }
        codeStream.recordPositionsFrom(pc, this.sourceStart);
        return;
      }
    }
    // null cases
    // optimized case: x == null
    if (this.right instanceof NullLiteral) {
      if (this.left instanceof NullLiteral) {
        // null == null
        if (valueRequired) {
          if (falseLabel == null) {
            // implicit falling through the FALSE case
            if (trueLabel != null) {
              codeStream.goto_(trueLabel);
            }
          }
        }
      } else {
        this.left.generateCode(currentScope, codeStream, valueRequired);
        if (valueRequired) {
          if (falseLabel == null) {
            if (trueLabel != null) {
              // implicit falling through the FALSE case
              codeStream.ifnull(trueLabel);
            }
          } else {
            // implicit falling through the TRUE case
            if (trueLabel == null) {
              codeStream.ifnonnull(falseLabel);
            } else {
              // no implicit fall through TRUE/FALSE --> should never occur
            }
          }
        }
      }
      codeStream.recordPositionsFrom(pc, this.sourceStart);
      return;
    } else if (this.left instanceof NullLiteral) { // optimized case: null == x
      this.right.generateCode(currentScope, codeStream, valueRequired);
      if (valueRequired) {
        if (falseLabel == null) {
          if (trueLabel != null) {
            // implicit falling through the FALSE case
            codeStream.ifnull(trueLabel);
          }
        } else {
          // implicit falling through the TRUE case
          if (trueLabel == null) {
            codeStream.ifnonnull(falseLabel);
          } else {
            // no implicit fall through TRUE/FALSE --> should never occur
          }
        }
      }
      codeStream.recordPositionsFrom(pc, this.sourceStart);
      return;
    }

    // default case
    this.left.generateCode(currentScope, codeStream, valueRequired);
    this.right.generateCode(currentScope, codeStream, valueRequired);
    if (valueRequired) {
      if (falseLabel == null) {
        if (trueLabel != null) {
          // implicit falling through the FALSE case
          switch ((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK)
              >> 4) { // operand runtime type
            case T_int:
              codeStream.if_icmpeq(trueLabel);
              break;
            case T_float:
              codeStream.fcmpl();
              codeStream.ifeq(trueLabel);
              break;
            case T_long:
              codeStream.lcmp();
              codeStream.ifeq(trueLabel);
              break;
            case T_double:
              codeStream.dcmpl();
              codeStream.ifeq(trueLabel);
              break;
            default:
              codeStream.if_acmpeq(trueLabel);
          }
        }
      } else {
        // implicit falling through the TRUE case
        if (trueLabel == null) {
          switch ((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK)
              >> 4) { // operand runtime type
            case T_int:
              codeStream.if_icmpne(falseLabel);
              break;
            case T_float:
              codeStream.fcmpl();
              codeStream.ifne(falseLabel);
              break;
            case T_long:
              codeStream.lcmp();
              codeStream.ifne(falseLabel);
              break;
            case T_double:
              codeStream.dcmpl();
              codeStream.ifne(falseLabel);
              break;
            default:
              codeStream.if_acmpne(falseLabel);
          }
        } else {
          // no implicit fall through TRUE/FALSE --> should never occur
        }
      }
    }
    codeStream.recordPositionsFrom(pc, this.sourceStart);
  }
コード例 #3
0
  /** Boolean generation for == with non-boolean operands */
  public void generateNonBooleanEqual(
      BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {

    boolean isEqualOperator = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL;
    if (((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK) >> 4) == T_int) {
      Constant cst;
      if ((cst = this.left.constant) != Constant.NotAConstant && cst.intValue() == 0) {
        // optimized case: 0 == x, 0 != x
        this.right.generateCode(currentScope, codeStream, valueRequired);
        if (valueRequired) {
          BranchLabel falseLabel = new BranchLabel(codeStream);
          if (isEqualOperator) {
            codeStream.ifne(falseLabel);
          } else {
            codeStream.ifeq(falseLabel);
          }
          // comparison is TRUE
          codeStream.iconst_1();
          if ((this.bits & IsReturnedValue) != 0) {
            codeStream.generateImplicitConversion(this.implicitConversion);
            codeStream.generateReturnBytecode(this);
            // comparison is FALSE
            falseLabel.place();
            codeStream.iconst_0();
          } else {
            BranchLabel endLabel = new BranchLabel(codeStream);
            codeStream.goto_(endLabel);
            codeStream.decrStackSize(1);
            // comparison is FALSE
            falseLabel.place();
            codeStream.iconst_0();
            endLabel.place();
          }
        }
        return;
      }
      if ((cst = this.right.constant) != Constant.NotAConstant && cst.intValue() == 0) {
        // optimized case: x == 0, x != 0
        this.left.generateCode(currentScope, codeStream, valueRequired);
        if (valueRequired) {
          BranchLabel falseLabel = new BranchLabel(codeStream);
          if (isEqualOperator) {
            codeStream.ifne(falseLabel);
          } else {
            codeStream.ifeq(falseLabel);
          }
          // comparison is TRUE
          codeStream.iconst_1();
          if ((this.bits & IsReturnedValue) != 0) {
            codeStream.generateImplicitConversion(this.implicitConversion);
            codeStream.generateReturnBytecode(this);
            // comparison is FALSE
            falseLabel.place();
            codeStream.iconst_0();
          } else {
            BranchLabel endLabel = new BranchLabel(codeStream);
            codeStream.goto_(endLabel);
            codeStream.decrStackSize(1);
            // comparison is FALSE
            falseLabel.place();
            codeStream.iconst_0();
            endLabel.place();
          }
        }
        return;
      }
    }

    // null cases
    if (this.right instanceof NullLiteral) {
      if (this.left instanceof NullLiteral) {
        // null == null, null != null
        if (valueRequired) {
          if (isEqualOperator) {
            codeStream.iconst_1();
          } else {
            codeStream.iconst_0();
          }
        }
      } else {
        // x == null, x != null
        this.left.generateCode(currentScope, codeStream, valueRequired);
        if (valueRequired) {
          BranchLabel falseLabel = new BranchLabel(codeStream);
          if (isEqualOperator) {
            codeStream.ifnonnull(falseLabel);
          } else {
            codeStream.ifnull(falseLabel);
          }
          // comparison is TRUE
          codeStream.iconst_1();
          if ((this.bits & IsReturnedValue) != 0) {
            codeStream.generateImplicitConversion(this.implicitConversion);
            codeStream.generateReturnBytecode(this);
            // comparison is FALSE
            falseLabel.place();
            codeStream.iconst_0();
          } else {
            BranchLabel endLabel = new BranchLabel(codeStream);
            codeStream.goto_(endLabel);
            codeStream.decrStackSize(1);
            // comparison is FALSE
            falseLabel.place();
            codeStream.iconst_0();
            endLabel.place();
          }
        }
      }
      return;
    } else if (this.left instanceof NullLiteral) {
      // null = x, null != x
      this.right.generateCode(currentScope, codeStream, valueRequired);
      if (valueRequired) {
        BranchLabel falseLabel = new BranchLabel(codeStream);
        if (isEqualOperator) {
          codeStream.ifnonnull(falseLabel);
        } else {
          codeStream.ifnull(falseLabel);
        }
        // comparison is TRUE
        codeStream.iconst_1();
        if ((this.bits & IsReturnedValue) != 0) {
          codeStream.generateImplicitConversion(this.implicitConversion);
          codeStream.generateReturnBytecode(this);
          // comparison is FALSE
          falseLabel.place();
          codeStream.iconst_0();
        } else {
          BranchLabel endLabel = new BranchLabel(codeStream);
          codeStream.goto_(endLabel);
          codeStream.decrStackSize(1);
          // comparison is FALSE
          falseLabel.place();
          codeStream.iconst_0();
          endLabel.place();
        }
      }
      return;
    }

    // default case
    this.left.generateCode(currentScope, codeStream, valueRequired);
    this.right.generateCode(currentScope, codeStream, valueRequired);
    if (valueRequired) {
      BranchLabel falseLabel = new BranchLabel(codeStream);
      if (isEqualOperator) {
        switch ((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK)
            >> 4) { // operand runtime type
          case T_int:
            codeStream.if_icmpne(falseLabel);
            break;
          case T_float:
            codeStream.fcmpl();
            codeStream.ifne(falseLabel);
            break;
          case T_long:
            codeStream.lcmp();
            codeStream.ifne(falseLabel);
            break;
          case T_double:
            codeStream.dcmpl();
            codeStream.ifne(falseLabel);
            break;
          default:
            codeStream.if_acmpne(falseLabel);
        }
      } else {
        switch ((this.left.implicitConversion & IMPLICIT_CONVERSION_MASK)
            >> 4) { // operand runtime type
          case T_int:
            codeStream.if_icmpeq(falseLabel);
            break;
          case T_float:
            codeStream.fcmpl();
            codeStream.ifeq(falseLabel);
            break;
          case T_long:
            codeStream.lcmp();
            codeStream.ifeq(falseLabel);
            break;
          case T_double:
            codeStream.dcmpl();
            codeStream.ifeq(falseLabel);
            break;
          default:
            codeStream.if_acmpeq(falseLabel);
        }
      }
      // comparison is TRUE
      codeStream.iconst_1();
      if ((this.bits & IsReturnedValue) != 0) {
        codeStream.generateImplicitConversion(this.implicitConversion);
        codeStream.generateReturnBytecode(this);
        // comparison is FALSE
        falseLabel.place();
        codeStream.iconst_0();
      } else {
        BranchLabel endLabel = new BranchLabel(codeStream);
        codeStream.goto_(endLabel);
        codeStream.decrStackSize(1);
        // comparison is FALSE
        falseLabel.place();
        codeStream.iconst_0();
        endLabel.place();
      }
    }
  }
コード例 #4
0
  /**
   * Boolean generation for == with boolean operands
   *
   * <p>Note this code does not optimize conditional constants !!!!
   */
  public void generateBooleanEqual(
      BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {

    // optimized cases: <something equivalent to true> == x, <something equivalent to false> == x,
    // optimized cases: <something equivalent to false> != x, <something equivalent to true> != x,
    boolean isEqualOperator = ((this.bits & OperatorMASK) >> OperatorSHIFT) == EQUAL_EQUAL;
    Constant cst = this.left.optimizedBooleanConstant();
    if (cst != Constant.NotAConstant) {
      Constant rightCst = this.right.optimizedBooleanConstant();
      if (rightCst != Constant.NotAConstant) {
        // <something equivalent to true> == <something equivalent to true>, <something equivalent
        // to false> != <something equivalent to true>
        // <something equivalent to true> == <something equivalent to false>, <something equivalent
        // to false> != <something equivalent to false>
        this.left.generateCode(currentScope, codeStream, false);
        this.right.generateCode(currentScope, codeStream, false);
        if (valueRequired) {
          boolean leftBool = cst.booleanValue();
          boolean rightBool = rightCst.booleanValue();
          if (isEqualOperator) {
            if (leftBool == rightBool) {
              codeStream.iconst_1();
            } else {
              codeStream.iconst_0();
            }
          } else {
            if (leftBool != rightBool) {
              codeStream.iconst_1();
            } else {
              codeStream.iconst_0();
            }
          }
        }
      } else if (cst.booleanValue() == isEqualOperator) {
        // <something equivalent to true> == x, <something equivalent to false> != x
        this.left.generateCode(currentScope, codeStream, false);
        this.right.generateCode(currentScope, codeStream, valueRequired);
      } else {
        // <something equivalent to false> == x, <something equivalent to true> != x
        if (valueRequired) {
          BranchLabel falseLabel = new BranchLabel(codeStream);
          this.left.generateCode(currentScope, codeStream, false);
          this.right.generateOptimizedBoolean(
              currentScope, codeStream, null, falseLabel, valueRequired);
          // comparison is TRUE
          codeStream.iconst_0();
          if ((this.bits & IsReturnedValue) != 0) {
            codeStream.generateImplicitConversion(this.implicitConversion);
            codeStream.generateReturnBytecode(this);
            // comparison is FALSE
            falseLabel.place();
            codeStream.iconst_1();
          } else {
            BranchLabel endLabel = new BranchLabel(codeStream);
            codeStream.goto_(endLabel);
            codeStream.decrStackSize(1);
            // comparison is FALSE
            falseLabel.place();
            codeStream.iconst_1();
            endLabel.place();
          }
        } else {
          this.left.generateCode(currentScope, codeStream, false);
          this.right.generateCode(currentScope, codeStream, false);
        }
        //				left.generateCode(currentScope, codeStream, false);
        //				right.generateCode(currentScope, codeStream, valueRequired);
        //				if (valueRequired) {
        //					codeStream.iconst_1();
        //					codeStream.ixor(); // negate
        //				}
      }
      return;
    }
    cst = this.right.optimizedBooleanConstant();
    if (cst != Constant.NotAConstant) {
      if (cst.booleanValue() == isEqualOperator) {
        // x == <something equivalent to true>, x != <something equivalent to false>
        this.left.generateCode(currentScope, codeStream, valueRequired);
        this.right.generateCode(currentScope, codeStream, false);
      } else {
        // x == <something equivalent to false>, x != <something equivalent to true>
        if (valueRequired) {
          BranchLabel falseLabel = new BranchLabel(codeStream);
          this.left.generateOptimizedBoolean(
              currentScope, codeStream, null, falseLabel, valueRequired);
          this.right.generateCode(currentScope, codeStream, false);
          // comparison is TRUE
          codeStream.iconst_0();
          if ((this.bits & IsReturnedValue) != 0) {
            codeStream.generateImplicitConversion(this.implicitConversion);
            codeStream.generateReturnBytecode(this);
            // comparison is FALSE
            falseLabel.place();
            codeStream.iconst_1();
          } else {
            BranchLabel endLabel = new BranchLabel(codeStream);
            codeStream.goto_(endLabel);
            codeStream.decrStackSize(1);
            // comparison is FALSE
            falseLabel.place();
            codeStream.iconst_1();
            endLabel.place();
          }
        } else {
          this.left.generateCode(currentScope, codeStream, false);
          this.right.generateCode(currentScope, codeStream, false);
        }
        //				left.generateCode(currentScope, codeStream, valueRequired);
        //				right.generateCode(currentScope, codeStream, false);
        //				if (valueRequired) {
        //					codeStream.iconst_1();
        //					codeStream.ixor(); // negate
        //				}
      }
      return;
    }
    // default case
    this.left.generateCode(currentScope, codeStream, valueRequired);
    this.right.generateCode(currentScope, codeStream, valueRequired);

    if (valueRequired) {
      if (isEqualOperator) {
        BranchLabel falseLabel;
        codeStream.if_icmpne(falseLabel = new BranchLabel(codeStream));
        // comparison is TRUE
        codeStream.iconst_1();
        if ((this.bits & IsReturnedValue) != 0) {
          codeStream.generateImplicitConversion(this.implicitConversion);
          codeStream.generateReturnBytecode(this);
          // comparison is FALSE
          falseLabel.place();
          codeStream.iconst_0();
        } else {
          BranchLabel endLabel = new BranchLabel(codeStream);
          codeStream.goto_(endLabel);
          codeStream.decrStackSize(1);
          // comparison is FALSE
          falseLabel.place();
          codeStream.iconst_0();
          endLabel.place();
        }
      } else {
        codeStream.ixor();
      }
    }
  }