/** Code generation for a array allocation expression */
  public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {

    int pc = codeStream.position;

    if (initializer != null) {
      initializer.generateCode(currentScope, codeStream, valueRequired);
      return;
    }

    int nonNullDimensionsLength = 0;
    for (int i = 0, max = dimensions.length; i < max; i++)
      if (dimensions[i] != null) {
        dimensions[i].generateCode(currentScope, codeStream, true);
        nonNullDimensionsLength++;
      }

    // Generate a sequence of bytecodes corresponding to an array allocation
    if (this.resolvedType.dimensions() == 1) {
      // Mono-dimensional array
      codeStream.newArray((ArrayBinding) this.resolvedType);
    } else {
      // Multi-dimensional array
      codeStream.multianewarray(this.resolvedType, nonNullDimensionsLength);
    }

    if (valueRequired) {
      codeStream.generateImplicitConversion(implicitConversion);
    } else {
      codeStream.pop();
    }

    codeStream.recordPositionsFrom(pc, this.sourceStart);
  }
 /**
  * Code generation for instanceOfExpression
  *
  * @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;
   this.expression.generateCode(currentScope, codeStream, true);
   codeStream.instance_of(this.type.resolvedType);
   if (valueRequired) {
     codeStream.generateImplicitConversion(this.implicitConversion);
   } else {
     codeStream.pop();
   }
   codeStream.recordPositionsFrom(pc, this.sourceStart);
 }
  /**
   * MessageSendDotClass code generation
   *
   * @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) {
    // {ObjectTeams: role class literal?
    if (this.roleClassLiteralAccess != null) {
      this.roleClassLiteralAccess.generateCode(currentScope, codeStream, valueRequired);
      return;
    }
    // SH}
    int pc = codeStream.position;

    // in interface case, no caching occurs, since cannot make a cache field for interface
    if (valueRequired) {
      codeStream.generateClassLiteralAccessForType(this.type.resolvedType, this.syntheticField);
      codeStream.generateImplicitConversion(this.implicitConversion);
    }
    codeStream.recordPositionsFrom(pc, this.sourceStart);
  }
  /** Code generation for a binary operation */
  public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
    int pc = codeStream.position;
    if (this.constant != Constant.NotAConstant) {
      // inlined value
      if (valueRequired) codeStream.generateConstant(this.constant, this.implicitConversion);
      codeStream.recordPositionsFrom(pc, this.sourceStart);
      return;
    }
    Constant cst = this.right.constant;
    if (cst != Constant.NotAConstant) {
      // <expr> || true --> true
      if (cst.booleanValue() == true) {
        this.left.generateCode(currentScope, codeStream, false);
        if (valueRequired) codeStream.iconst_1();
      } else {
        // <expr>|| false --> <expr>
        this.left.generateCode(currentScope, codeStream, valueRequired);
      }
      if (this.mergedInitStateIndex != -1) {
        codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex);
      }
      codeStream.generateImplicitConversion(this.implicitConversion);
      codeStream.recordPositionsFrom(pc, this.sourceStart);
      return;
    }

    BranchLabel trueLabel = new BranchLabel(codeStream), endLabel;
    cst = this.left.optimizedBooleanConstant();
    boolean leftIsConst = cst != Constant.NotAConstant;
    boolean leftIsTrue = leftIsConst && cst.booleanValue() == true;

    cst = this.right.optimizedBooleanConstant();
    boolean rightIsConst = cst != Constant.NotAConstant;
    boolean rightIsTrue = rightIsConst && cst.booleanValue() == true;

    generateOperands:
    {
      if (leftIsConst) {
        this.left.generateCode(currentScope, codeStream, false);
        if (leftIsTrue) {
          break generateOperands; // no need to generate right operand
        }
      } else {
        this.left.generateOptimizedBoolean(currentScope, codeStream, trueLabel, null, true);
        // need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1
      }
      if (this.rightInitStateIndex != -1) {
        codeStream.addDefinitelyAssignedVariables(currentScope, this.rightInitStateIndex);
      }
      if (rightIsConst) {
        this.right.generateCode(currentScope, codeStream, false);
      } else {
        this.right.generateOptimizedBoolean(
            currentScope, codeStream, trueLabel, null, valueRequired);
      }
    }
    if (this.mergedInitStateIndex != -1) {
      codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex);
    }
    /*
     * 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 (valueRequired) {
      if (leftIsConst && leftIsTrue) {
        codeStream.iconst_1();
        codeStream.recordPositionsFrom(codeStream.position, this.left.sourceEnd);
      } else {
        if (rightIsConst && rightIsTrue) {
          codeStream.iconst_1();
          codeStream.recordPositionsFrom(codeStream.position, this.left.sourceEnd);
        } else {
          codeStream.iconst_0();
        }
        if (trueLabel.forwardReferenceCount() > 0) {
          if ((this.bits & IsReturnedValue) != 0) {
            codeStream.generateImplicitConversion(this.implicitConversion);
            codeStream.generateReturnBytecode(this);
            trueLabel.place();
            codeStream.iconst_1();
          } else {
            codeStream.goto_(endLabel = new BranchLabel(codeStream));
            codeStream.decrStackSize(1);
            trueLabel.place();
            codeStream.iconst_1();
            endLabel.place();
          }
        } else {
          trueLabel.place();
        }
      }
      codeStream.generateImplicitConversion(this.implicitConversion);
      codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd);
    } else {
      trueLabel.place();
    }
  }
  public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {
    if (!valueRequired) currentScope.problemReporter().unusedObjectAllocation(this);

    int pc = codeStream.position;
    MethodBinding codegenBinding = this.binding.original();
    ReferenceBinding allocatedType = codegenBinding.declaringClass;

    codeStream.new_(allocatedType);
    boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
    if (valueRequired || isUnboxing) {
      codeStream.dup();
    }
    // better highlight for allocation: display the type individually
    if (this.type != null) { // null for enum constant body
      codeStream.recordPositionsFrom(pc, this.type.sourceStart);
    } else {
      // push enum constant name and ordinal
      codeStream.ldc(String.valueOf(this.enumConstant.name));
      codeStream.generateInlinedValue(this.enumConstant.binding.id);
    }

    // handling innerclass instance allocation - enclosing instance arguments
    if (allocatedType.isNestedType()) {
      codeStream.generateSyntheticEnclosingInstanceValues(
          currentScope, allocatedType, enclosingInstance(), this);
    }
    // generate the arguments for constructor
    generateArguments(this.binding, this.arguments, currentScope, codeStream);
    // handling innerclass instance allocation - outer local arguments
    if (allocatedType.isNestedType()) {
      codeStream.generateSyntheticOuterArgumentValues(currentScope, allocatedType, this);
    }
    // invoke constructor
    if (this.syntheticAccessor == null) {
      codeStream.invoke(
          Opcodes.OPC_invokespecial, codegenBinding, null /* default declaringClass */);
    } else {
      // synthetic accessor got some extra arguments appended to its signature, which need values
      for (int i = 0,
              max = this.syntheticAccessor.parameters.length - codegenBinding.parameters.length;
          i < max;
          i++) {
        codeStream.aconst_null();
      }
      codeStream.invoke(
          Opcodes.OPC_invokespecial, this.syntheticAccessor, null /* default declaringClass */);
    }
    if (valueRequired) {
      codeStream.generateImplicitConversion(this.implicitConversion);
    } else if (isUnboxing) {
      // conversion only generated if unboxing
      codeStream.generateImplicitConversion(this.implicitConversion);
      switch (postConversionType(currentScope).id) {
        case T_long:
        case T_double:
          codeStream.pop2();
          break;
        default:
          codeStream.pop();
      }
    }
    codeStream.recordPositionsFrom(pc, this.sourceStart);
  }
示例#6
0
  /** Code generation for a array initializer */
  public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {

    // Flatten the values and compute the dimensions, by iterating in depth into nested array
    // initializers
    int pc = codeStream.position;
    int expressionLength = (this.expressions == null) ? 0 : this.expressions.length;
    codeStream.generateInlinedValue(expressionLength);
    codeStream.newArray(this.binding);
    if (this.expressions != null) {
      // binding is an ArrayType, so I can just deal with the dimension
      int elementsTypeID = this.binding.dimensions > 1 ? -1 : this.binding.leafComponentType.id;
      for (int i = 0; i < expressionLength; i++) {
        Expression expr;
        if ((expr = this.expressions[i]).constant != Constant.NotAConstant) {
          switch (elementsTypeID) { // filter out initializations to default values
            case T_int:
            case T_short:
            case T_byte:
            case T_char:
            case T_long:
              if (expr.constant.longValue() != 0) {
                codeStream.dup();
                codeStream.generateInlinedValue(i);
                expr.generateCode(currentScope, codeStream, true);
                codeStream.arrayAtPut(elementsTypeID, false);
              }
              break;
            case T_float:
            case T_double:
              double constantValue = expr.constant.doubleValue();
              if (constantValue == -0.0 || constantValue != 0) {
                codeStream.dup();
                codeStream.generateInlinedValue(i);
                expr.generateCode(currentScope, codeStream, true);
                codeStream.arrayAtPut(elementsTypeID, false);
              }
              break;
            case T_boolean:
              if (expr.constant.booleanValue() != false) {
                codeStream.dup();
                codeStream.generateInlinedValue(i);
                expr.generateCode(currentScope, codeStream, true);
                codeStream.arrayAtPut(elementsTypeID, false);
              }
              break;
            default:
              if (!(expr instanceof NullLiteral)) {
                codeStream.dup();
                codeStream.generateInlinedValue(i);
                expr.generateCode(currentScope, codeStream, true);
                codeStream.arrayAtPut(elementsTypeID, false);
              }
          }
        } else if (!(expr instanceof NullLiteral)) {
          codeStream.dup();
          codeStream.generateInlinedValue(i);
          expr.generateCode(currentScope, codeStream, true);
          codeStream.arrayAtPut(elementsTypeID, false);
        }
      }
    }
    if (valueRequired) {
      codeStream.generateImplicitConversion(this.implicitConversion);
    } else {
      codeStream.pop();
    }
    codeStream.recordPositionsFrom(pc, this.sourceStart);
  }