/** 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);
 }
  /** Do statement code generation */
  public void generateCode(BlockScope currentScope, CodeStream codeStream) {
    if ((this.bits & ASTNode.IsReachable) == 0) {
      return;
    }
    int pc = codeStream.position;

    // labels management
    BranchLabel actionLabel = new BranchLabel(codeStream);
    if (this.action != null) actionLabel.tagBits |= BranchLabel.USED;
    actionLabel.place();
    this.breakLabel.initialize(codeStream);
    boolean hasContinueLabel = this.continueLabel != null;
    if (hasContinueLabel) {
      this.continueLabel.initialize(codeStream);
    }

    // generate action
    if (this.action != null) {
      this.action.generateCode(currentScope, codeStream);
    }
    // continue label (135602)
    if (hasContinueLabel) {
      this.continueLabel.place();
      // May loose some local variable initializations : affecting the local variable attributes
      if (this.preConditionInitStateIndex != -1) {
        codeStream.removeNotDefinitelyAssignedVariables(
            currentScope, this.preConditionInitStateIndex);
        codeStream.addDefinitelyAssignedVariables(currentScope, this.preConditionInitStateIndex);
      }
      // generate condition
      Constant cst = this.condition.optimizedBooleanConstant();
      boolean isConditionOptimizedFalse =
          cst != Constant.NotAConstant && cst.booleanValue() == false;
      if (isConditionOptimizedFalse) {
        this.condition.generateCode(currentScope, codeStream, false);
      } else {
        this.condition.generateOptimizedBoolean(currentScope, codeStream, actionLabel, null, true);
      }
    }
    // May loose some local variable initializations : affecting the local variable attributes
    if (this.mergedInitStateIndex != -1) {
      codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex);
      codeStream.addDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex);
    }
    if (this.breakLabel.forwardReferenceCount() > 0) {
      this.breakLabel.place();
    }

    codeStream.recordPositionsFrom(pc, this.sourceStart);
  }
Beispiel #4
0
 /**
  * Cast expression 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) {
   int pc = codeStream.position;
   boolean needRuntimeCheckcast = (this.bits & ASTNode.GenerateCheckcast) != 0;
   if (this.constant != Constant.NotAConstant) {
     if (valueRequired
         || needRuntimeCheckcast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting
       // check
       codeStream.generateConstant(this.constant, this.implicitConversion);
       if (needRuntimeCheckcast) {
         codeStream.checkcast(this.resolvedType);
       }
       if (!valueRequired) {
         // the resolveType cannot be double or long
         codeStream.pop();
       }
     }
     codeStream.recordPositionsFrom(pc, this.sourceStart);
     return;
   }
   this.expression.generateCode(currentScope, codeStream, valueRequired || needRuntimeCheckcast);
   if (needRuntimeCheckcast
       && this.expression.postConversionType(currentScope)
           != this.resolvedType
               .erasure()) { // no need to issue a checkcast if already done as genericCast
     codeStream.checkcast(this.resolvedType);
   }
   if (valueRequired) {
     codeStream.generateImplicitConversion(this.implicitConversion);
   } else if (needRuntimeCheckcast) {
     codeStream.pop();
   }
   codeStream.recordPositionsFrom(pc, this.sourceStart);
 }
  /**
   * 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);
  }
  /**
   * 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);
  }
Beispiel #7
0
  /* (non-Javadoc)
   * @see org.eclipse.jdt.internal.compiler.ast.SubRoutineStatement#generateSubRoutineInvocation(org.eclipse.jdt.internal.compiler.lookup.BlockScope, org.eclipse.jdt.internal.compiler.codegen.CodeStream)
   */
  public void generateSubRoutineInvocation(BlockScope currentScope, CodeStream codeStream) {

    if (this.isSubRoutineEscaping) {
      codeStream.goto_(this.subRoutineStartLabel);
    } else {
      if (currentScope.compilerOptions().inlineJsrBytecode) {
        // cannot use jsr bytecode, then simply inline the subroutine
        this.exitAnyExceptionHandler();
        this.finallyBlock.generateCode(currentScope, codeStream);
        this.enterAnyExceptionHandler(codeStream);
      } else {
        // classic subroutine invocation, distinguish case of non-returning subroutine
        codeStream.jsr(this.subRoutineStartLabel);
      }
    }
  }
 public void generateOptimizedStringConcatenationCreation(
     BlockScope blockScope, CodeStream codeStream, int typeID) {
   // keep implementation in sync with BinaryExpression
   // #generateOptimizedStringConcatenationCreation
   if (this.referencesTable == null) {
     super.generateOptimizedStringConcatenationCreation(blockScope, codeStream, typeID);
   } else {
     if ((((this.bits & ASTNode.OperatorMASK) >> ASTNode.OperatorSHIFT) == OperatorIds.PLUS)
         && ((this.bits & ASTNode.ReturnTypeIDMASK) == TypeIds.T_JavaLangString)
         && this.constant == Constant.NotAConstant) {
       int pc = codeStream.position;
       BinaryExpression cursor = this.referencesTable[this.arity - 1];
       // silence warnings
       int restart = 0;
       for (restart = this.arity - 1; restart >= 0; restart--) {
         if (((((cursor = this.referencesTable[restart]).bits & ASTNode.OperatorMASK)
                     >> ASTNode.OperatorSHIFT)
                 == OperatorIds.PLUS)
             && ((cursor.bits & ASTNode.ReturnTypeIDMASK) == TypeIds.T_JavaLangString)) {
           if (cursor.constant != Constant.NotAConstant) {
             codeStream.newStringContatenation(); // new: java.lang.StringBuffer
             codeStream.dup();
             codeStream.ldc(cursor.constant.stringValue());
             codeStream.invokeStringConcatenationStringConstructor();
             // invokespecial: java.lang.StringBuffer.<init>(Ljava.lang.String;)V
             break;
           }
         } else {
           cursor.generateOptimizedStringConcatenationCreation(
               blockScope, codeStream, cursor.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
           break;
         }
       }
       restart++;
       if (restart == 0) { // reached the leftmost expression
         cursor.left.generateOptimizedStringConcatenationCreation(
             blockScope, codeStream, cursor.left.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
       }
       int pcAux;
       for (int i = restart; i < this.arity; i++) {
         codeStream.recordPositionsFrom(pc, (cursor = this.referencesTable[i]).left.sourceStart);
         pcAux = codeStream.position;
         cursor.right.generateOptimizedStringConcatenation(
             blockScope, codeStream, cursor.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
         codeStream.recordPositionsFrom(pcAux, cursor.right.sourceStart);
       }
       codeStream.recordPositionsFrom(pc, this.left.sourceStart);
       pc = codeStream.position;
       this.right.generateOptimizedStringConcatenation(
           blockScope, codeStream, this.right.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
       codeStream.recordPositionsFrom(pc, this.right.sourceStart);
     } else {
       super.generateOptimizedStringConcatenationCreation(blockScope, codeStream, typeID);
     }
   }
 }
  /**
   * Normal == or != 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) {

    int pc = codeStream.position;
    if (this.constant != Constant.NotAConstant) {
      if (valueRequired) codeStream.generateConstant(this.constant, this.implicitConversion);
      codeStream.recordPositionsFrom(pc, this.sourceStart);
      return;
    }

    if ((this.left.implicitConversion & COMPILE_TYPE_MASK) /*compile-time*/ == T_boolean) {
      generateBooleanEqual(currentScope, codeStream, valueRequired);
    } else {
      generateNonBooleanEqual(currentScope, codeStream, valueRequired);
    }
    if (valueRequired) {
      codeStream.generateImplicitConversion(this.implicitConversion);
    }
    codeStream.recordPositionsFrom(pc, this.sourceStart);
  }
  public void generateCode(BlockScope currentScope, CodeStream codeStream) {
    if ((this.bits & IsReachable) == 0) {
      return;
    }
    int pc = codeStream.position;

    if (this.assertionSyntheticFieldBinding != null) {
      BranchLabel assertionActivationLabel = new BranchLabel(codeStream);
      codeStream.fieldAccess(
          Opcodes.OPC_getstatic,
          this.assertionSyntheticFieldBinding,
          null /* default declaringClass */);
      codeStream.ifne(assertionActivationLabel);

      BranchLabel falseLabel;
      this.assertExpression.generateOptimizedBoolean(
          currentScope, codeStream, (falseLabel = new BranchLabel(codeStream)), null, true);
      codeStream.newJavaLangAssertionError();
      codeStream.dup();
      if (this.exceptionArgument != null) {
        this.exceptionArgument.generateCode(currentScope, codeStream, true);
        codeStream.invokeJavaLangAssertionErrorConstructor(
            this.exceptionArgument.implicitConversion & 0xF);
      } else {
        codeStream.invokeJavaLangAssertionErrorDefaultConstructor();
      }
      codeStream.athrow();

      // May loose some local variable initializations : affecting the local variable attributes
      if (this.preAssertInitStateIndex != -1) {
        codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preAssertInitStateIndex);
      }
      falseLabel.place();
      assertionActivationLabel.place();
    } else {
      // May loose some local variable initializations : affecting the local variable attributes
      if (this.preAssertInitStateIndex != -1) {
        codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.preAssertInitStateIndex);
      }
    }
    codeStream.recordPositionsFrom(pc, this.sourceStart);
  }
 public void generateCode(BlockScope var1, CodeStream var2) {
   if ((this.field_446 & Integer.MIN_VALUE) != 0) {
     int var3 = var2.field_1208;
     boolean var4;
     if (this.initialization != null
         && (!(var4 = this.binding.method_431())
             || this.binding.constant() == Constant.NotAConstant)) {
       if (!var4) {
         var2.method_2093();
       }
       this.initialization.generateCode(var1, var2, true);
       if (var4) {
         var2.method_2357(this.binding);
       } else {
         var2.method_2356(this.binding);
       }
     }
     var2.method_2360(var3, this.field_444);
   }
 }
 /**
  * Cast expression 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) {
   int pc = codeStream.position;
   boolean annotatedCast = (this.type.bits & ASTNode.HasTypeAnnotations) != 0;
   boolean needRuntimeCheckcast = (this.bits & ASTNode.GenerateCheckcast) != 0;
   if (this.constant != Constant.NotAConstant) {
     if (valueRequired
         || needRuntimeCheckcast
         || annotatedCast) { // Added for: 1F1W9IG: IVJCOM:WINNT - Compiler omits casting check
       codeStream.generateConstant(this.constant, this.implicitConversion);
       if (needRuntimeCheckcast || annotatedCast) {
         codeStream.checkcast(this.type, this.resolvedType, pc);
       }
       if (!valueRequired) {
         // the resolveType cannot be double or long
         codeStream.pop();
       }
     }
     codeStream.recordPositionsFrom(pc, this.sourceStart);
     return;
   }
   this.expression.generateCode(
       currentScope, codeStream, annotatedCast || valueRequired || needRuntimeCheckcast);
   if (annotatedCast
       || (needRuntimeCheckcast
           && TypeBinding.notEquals(
               this.expression.postConversionType(currentScope),
               this.resolvedType
                   .erasure()))) { // no need to issue a checkcast if already done as genericCast
     codeStream.checkcast(this.type, this.resolvedType, pc);
   }
   if (valueRequired) {
     codeStream.generateImplicitConversion(this.implicitConversion);
   } else if (annotatedCast || needRuntimeCheckcast) {
     switch (this.resolvedType.id) {
       case T_long:
       case T_double:
         codeStream.pop2();
         break;
       default:
         codeStream.pop();
         break;
     }
   }
   codeStream.recordPositionsFrom(pc, this.sourceStart);
 }
 public void generateAssignment(
     BlockScope currentScope,
     CodeStream codeStream,
     Assignment assignment,
     boolean valueRequired) {
   int pc = codeStream.position;
   FieldBinding codegenBinding = this.binding.original();
   this.receiver.generateCode(currentScope, codeStream, !codegenBinding.isStatic());
   codeStream.recordPositionsFrom(pc, this.sourceStart);
   assignment.expression.generateCode(currentScope, codeStream, true);
   fieldStore(
       currentScope,
       codeStream,
       codegenBinding,
       this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE],
       this.actualReceiverType,
       this.receiver.isImplicitThis(),
       valueRequired);
   if (valueRequired) {
     codeStream.generateImplicitConversion(assignment.implicitConversion);
   }
   // no need for generic cast as value got dupped
 }
  public void generateStoreSaveValueIfNecessary(CodeStream codeStream) {

    // push receiver
    codeStream.aload_0();

    // push the 2 parameters of "setResult(Object, Class)"
    if (this.expression == null
        || this.expression.resolvedType
            == TypeBinding
                .VOID) { // expressionType == VoidBinding if code snippet is the expression
                         // "System.out.println()"
      // push null
      codeStream.aconst_null();

      // void.class
      codeStream.generateClassLiteralAccessForType(TypeBinding.VOID, null);
    } else {
      // swap with expression
      int valueTypeID = this.expression.resolvedType.id;
      if (valueTypeID == T_long || valueTypeID == T_double) {
        codeStream.dup_x2();
        codeStream.pop();
      } else {
        codeStream.swap();
      }

      // generate wrapper if needed
      if (this.expression.resolvedType.isBaseType()
          && this.expression.resolvedType != TypeBinding.NULL) {
        codeStream.generateBoxingConversion(this.expression.resolvedType.id);
      }

      // generate the expression type
      codeStream.generateClassLiteralAccessForType(this.expression.resolvedType, null);
    }

    // generate the invoke virtual to "setResult(Object,Class)"
    codeStream.invoke(
        Opcodes.OPC_invokevirtual, this.setResultMethod, null /* default declaringClass */);
  }
  public void generateCode(ClassFile classFile) {

    classFile.generateMethodInfoHeader(this.binding);
    int methodAttributeOffset = classFile.contentsOffset;
    int attributeNumber = classFile.generateMethodInfoAttributes(this.binding);
    if ((!this.binding.isNative()) && (!this.binding.isAbstract())) {
      int codeAttributeOffset = classFile.contentsOffset;
      classFile.generateCodeAttributeHeader();
      CodeStream codeStream = classFile.codeStream;
      codeStream.reset(this, classFile);
      // initialize local positions
      this.scope.computeLocalVariablePositions(this.binding.isStatic() ? 0 : 1, codeStream);

      // arguments initialization for local variable debug attributes
      if (this.arguments != null) {
        for (int i = 0, max = this.arguments.length; i < max; i++) {
          LocalVariableBinding argBinding;
          codeStream.addVisibleLocalVariable(argBinding = this.arguments[i].binding);
          argBinding.recordInitializationStartPC(0);
        }
      }
      if (this.statements != null) {
        for (int i = 0, max = this.statements.length; i < max; i++)
          this.statements[i].generateCode(this.scope, codeStream);
      }
      // if a problem got reported during code gen, then trigger problem method creation
      if (this.ignoreFurtherInvestigation) {
        throw new AbortMethod(this.scope.referenceCompilationUnit().compilationResult, null);
      }
      if ((this.bits & ASTNode.NeedFreeReturn) != 0) {
        codeStream.return_();
      }
      // local variable attributes
      codeStream.exitUserScope(this.scope);
      codeStream.recordPositionsFrom(0, this.declarationSourceEnd);
      try {
        classFile.completeCodeAttribute(codeAttributeOffset);
      } catch (NegativeArraySizeException e) {
        throw new AbortMethod(this.scope.referenceCompilationUnit().compilationResult, null);
      }
      attributeNumber++;
    } else {
      checkArgumentsSize();
    }
    classFile.completeMethodInfo(this.binding, methodAttributeOffset, attributeNumber);
  }
  /**
   * 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();
      }
    }
  }
  /** 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();
      }
    }
  }
  /** Generate invocation arguments, considering varargs methods */
  public void generateArguments(
      MethodBinding binding,
      Expression[] arguments,
      BlockScope currentScope,
      CodeStream codeStream) {
    if (binding.isVarargs()) {
      // 5 possibilities exist for a call to the vararg method foo(int i, int ... value) :
      //      foo(1), foo(1, null), foo(1, 2), foo(1, 2, 3, 4) & foo(1, new int[] {1, 2})
      TypeBinding[] params = binding.parameters;
      int paramLength = params.length;
      int varArgIndex = paramLength - 1;
      for (int i = 0; i < varArgIndex; i++) {
        arguments[i].generateCode(currentScope, codeStream, true);
      }
      ArrayBinding varArgsType =
          (ArrayBinding) params[varArgIndex]; // parameterType has to be an array type
      ArrayBinding codeGenVarArgsType = (ArrayBinding) binding.parameters[varArgIndex].erasure();
      int elementsTypeID = varArgsType.elementsType().id;
      int argLength = arguments == null ? 0 : arguments.length;

      if (argLength > paramLength) {
        // right number but not directly compatible or too many arguments - wrap extra into array
        // called with (argLength - lastIndex) elements : foo(1, 2) or foo(1, 2, 3, 4)
        // need to gen elements into an array, then gen each remaining element into created array
        codeStream.generateInlinedValue(argLength - varArgIndex);
        codeStream.newArray(null, codeGenVarArgsType); // create a mono-dimensional array
        for (int i = varArgIndex; i < argLength; i++) {
          codeStream.dup();
          codeStream.generateInlinedValue(i - varArgIndex);
          arguments[i].generateCode(currentScope, codeStream, true);
          codeStream.arrayAtPut(elementsTypeID, false);
        }
      } else if (argLength == paramLength) {
        // right number of arguments - could be inexact - pass argument as is
        TypeBinding lastType = arguments[varArgIndex].resolvedType;
        if (lastType == TypeBinding.NULL
            || (varArgsType.dimensions() == lastType.dimensions()
                && lastType.isCompatibleWith(varArgsType))) {
          // foo(1, new int[]{2, 3}) or foo(1, null) --> last arg is passed as-is
          arguments[varArgIndex].generateCode(currentScope, codeStream, true);
        } else {
          // right number but not directly compatible or too many arguments - wrap extra into array
          // need to gen elements into an array, then gen each remaining element into created array
          codeStream.generateInlinedValue(1);
          codeStream.newArray(null, codeGenVarArgsType); // create a mono-dimensional array
          codeStream.dup();
          codeStream.generateInlinedValue(0);
          arguments[varArgIndex].generateCode(currentScope, codeStream, true);
          codeStream.arrayAtPut(elementsTypeID, false);
        }
      } else { // not enough arguments - pass extra empty array
        // scenario: foo(1) --> foo(1, new int[0])
        // generate code for an empty array of parameterType
        codeStream.generateInlinedValue(0);
        codeStream.newArray(null, codeGenVarArgsType); // create a mono-dimensional array
      }
    } else if (arguments != null) { // standard generation for method arguments
      for (int i = 0, max = arguments.length; i < max; i++)
        arguments[i].generateCode(currentScope, codeStream, true);
    }
  }
  /** 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);
  }
  /**
   * MessageSend 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) {
    int pc = codeStream.position;
    MethodBinding codegenBinding = this.binding.original();
    if (codegenBinding.canBeSeenBy(this.actualReceiverType, this, currentScope)) {
      // generate receiver/enclosing instance access
      boolean isStatic = codegenBinding.isStatic();
      // outer access ?
      if (!isStatic && ((this.bits & DepthMASK) != 0)) {
        // outer method can be reached through emulation
        ReferenceBinding targetType =
            currentScope
                .enclosingSourceType()
                .enclosingTypeAt((this.bits & DepthMASK) >> DepthSHIFT);
        Object[] path =
            currentScope.getEmulationPath(
                targetType, true /*only exact match*/, false /*consider enclosing arg*/);
        if (path == null) {
          // emulation was not possible (should not happen per construction)
          currentScope.problemReporter().needImplementation(this);
        } else {
          codeStream.generateOuterAccess(path, this, targetType, currentScope);
        }
      } else {
        this.receiver.generateCode(currentScope, codeStream, !isStatic);
        if ((this.bits & NeedReceiverGenericCast) != 0) {
          codeStream.checkcast(this.actualReceiverType);
        }
        codeStream.recordPositionsFrom(pc, this.sourceStart);
      }
      // generate arguments
      generateArguments(this.binding, this.arguments, currentScope, codeStream);
      // actual message invocation
      TypeBinding constantPoolDeclaringClass =
          CodeStream.getConstantPoolDeclaringClass(
              currentScope,
              codegenBinding,
              this.actualReceiverType,
              this.receiver.isImplicitThis());
      if (isStatic) {
        codeStream.invoke(Opcodes.OPC_invokestatic, codegenBinding, constantPoolDeclaringClass);
      } else if ((this.receiver.isSuper()) || codegenBinding.isPrivate()) {
        codeStream.invoke(Opcodes.OPC_invokespecial, codegenBinding, constantPoolDeclaringClass);
      } else {
        if (constantPoolDeclaringClass.isInterface()) { // interface or annotation type
          codeStream.invoke(
              Opcodes.OPC_invokeinterface, codegenBinding, constantPoolDeclaringClass);
        } else {
          codeStream.invoke(Opcodes.OPC_invokevirtual, codegenBinding, constantPoolDeclaringClass);
        }
      }
    } else {
      codeStream.generateEmulationForMethod(currentScope, codegenBinding);
      // generate receiver/enclosing instance access
      boolean isStatic = codegenBinding.isStatic();
      // outer access ?
      if (!isStatic && ((this.bits & DepthMASK) != 0)) {
        // not supported yet
        currentScope.problemReporter().needImplementation(this);
      } else {
        this.receiver.generateCode(currentScope, codeStream, !isStatic);
        if ((this.bits & NeedReceiverGenericCast) != 0) {
          codeStream.checkcast(this.actualReceiverType);
        }
        codeStream.recordPositionsFrom(pc, this.sourceStart);
      }
      if (isStatic) {
        // we need an object on the stack which is ignored for the method invocation
        codeStream.aconst_null();
      }
      // generate arguments
      if (this.arguments != null) {
        int argsLength = this.arguments.length;
        codeStream.generateInlinedValue(argsLength);
        codeStream.newArray(
            currentScope.createArrayType(
                currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1));
        codeStream.dup();
        for (int i = 0; i < argsLength; i++) {
          codeStream.generateInlinedValue(i);
          this.arguments[i].generateCode(currentScope, codeStream, true);
          TypeBinding parameterBinding = codegenBinding.parameters[i];
          if (parameterBinding.isBaseType() && parameterBinding != TypeBinding.NULL) {
            codeStream.generateBoxingConversion(codegenBinding.parameters[i].id);
          }
          codeStream.aastore();
          if (i < argsLength - 1) {
            codeStream.dup();
          }
        }
      } else {
        codeStream.generateInlinedValue(0);
        codeStream.newArray(
            currentScope.createArrayType(
                currentScope.getType(TypeConstants.JAVA_LANG_OBJECT, 3), 1));
      }
      codeStream.invokeJavaLangReflectMethodInvoke();

      // convert the return value to the appropriate type for primitive types
      if (codegenBinding.returnType.isBaseType()) {
        int typeID = codegenBinding.returnType.id;
        if (typeID == T_void) {
          // remove the null from the stack
          codeStream.pop();
        }
        codeStream.checkcast(typeID);
        codeStream.getBaseTypeValue(typeID);
      } else {
        codeStream.checkcast(codegenBinding.returnType);
      }
    }
    // required cast must occur even if no value is required
    if (this.valueCast != null) codeStream.checkcast(this.valueCast);
    if (valueRequired) {
      // implicit conversion if necessary
      codeStream.generateImplicitConversion(this.implicitConversion);
    } else {
      boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
      // conversion only generated if unboxing
      if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
      switch (isUnboxing ? postConversionType(currentScope).id : codegenBinding.returnType.id) {
        case T_long:
        case T_double:
          codeStream.pop2();
          break;
        case T_void:
          break;
        default:
          codeStream.pop();
      }
    }
    codeStream.recordPositionsFrom(
        pc, (int) (this.nameSourcePosition >>> 32)); // highlight selector
  }
  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);

    if (this.anonymousType != null) {
      this.anonymousType.generateCode(currentScope, codeStream);
    }
  }
  /** Boolean operator code generation Optimized operations are: || */
  public void generateOptimizedBoolean(
      BlockScope currentScope,
      CodeStream codeStream,
      BranchLabel trueLabel,
      BranchLabel falseLabel,
      boolean valueRequired) {
    if (this.constant != Constant.NotAConstant) {
      super.generateOptimizedBoolean(
          currentScope, codeStream, trueLabel, falseLabel, valueRequired);
      return;
    }

    // <expr> || false --> <expr>
    Constant cst = this.right.constant;
    if (cst != Constant.NotAConstant && cst.booleanValue() == false) {
      int pc = codeStream.position;
      this.left.generateOptimizedBoolean(
          currentScope, codeStream, trueLabel, falseLabel, valueRequired);
      if (this.mergedInitStateIndex != -1) {
        codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex);
      }
      codeStream.recordPositionsFrom(pc, this.sourceStart);
      return;
    }

    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;

    // default case
    generateOperands:
    {
      if (falseLabel == null) {
        if (trueLabel != null) {
          // implicit falling through the FALSE case
          this.left.generateOptimizedBoolean(
              currentScope, codeStream, trueLabel, null, !leftIsConst);
          // need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1
          if (leftIsTrue) {
            if (valueRequired) codeStream.goto_(trueLabel);
            codeStream.recordPositionsFrom(codeStream.position, this.left.sourceEnd);
            break generateOperands; // no need to generate right operand
          }
          if (this.rightInitStateIndex != -1) {
            codeStream.addDefinitelyAssignedVariables(currentScope, this.rightInitStateIndex);
          }
          this.right.generateOptimizedBoolean(
              currentScope, codeStream, trueLabel, null, valueRequired && !rightIsConst);
          if (valueRequired && rightIsTrue) {
            codeStream.goto_(trueLabel);
            codeStream.recordPositionsFrom(codeStream.position, this.sourceEnd);
          }
        }
      } else {
        // implicit falling through the TRUE case
        if (trueLabel == null) {
          BranchLabel internalTrueLabel = new BranchLabel(codeStream);
          this.left.generateOptimizedBoolean(
              currentScope, codeStream, internalTrueLabel, null, !leftIsConst);
          // need value, e.g. if (a == 1 || ((b = 2) > 0)) {} -> shouldn't initialize 'b' if a==1
          if (leftIsTrue) {
            internalTrueLabel.place();
            break generateOperands; // no need to generate right operand
          }
          if (this.rightInitStateIndex != -1) {
            codeStream.addDefinitelyAssignedVariables(currentScope, this.rightInitStateIndex);
          }
          this.right.generateOptimizedBoolean(
              currentScope, codeStream, null, falseLabel, valueRequired && !rightIsConst);
          int pc = codeStream.position;
          if (valueRequired && rightIsConst && !rightIsTrue) {
            codeStream.goto_(falseLabel);
            codeStream.recordPositionsFrom(pc, this.sourceEnd);
          }
          internalTrueLabel.place();
        } else {
          // no implicit fall through TRUE/FALSE --> should never occur
        }
      }
    }
    if (this.mergedInitStateIndex != -1) {
      codeStream.removeNotDefinitelyAssignedVariables(currentScope, this.mergedInitStateIndex);
    }
  }
Beispiel #23
0
  /** Code generation for string literal */
  public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean valueRequired) {

    int pc = codeStream.position;
    if (valueRequired) codeStream.ldc(constant.stringValue());
    codeStream.recordPositionsFrom(pc, this.sourceStart);
  }
  /** Dump the suitable return bytecode for a return statement */
  public void generateReturnBytecode(CodeStream codeStream) {

    // output the return bytecode
    codeStream.return_();
  }
 /**
  * Field reference 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) {
   int pc = codeStream.position;
   if (this.constant != Constant.NotAConstant) {
     if (valueRequired) {
       codeStream.generateConstant(this.constant, this.implicitConversion);
     }
     codeStream.recordPositionsFrom(pc, this.sourceStart);
     return;
   }
   FieldBinding codegenBinding = this.binding.original();
   boolean isStatic = codegenBinding.isStatic();
   boolean isThisReceiver = this.receiver instanceof ThisReference;
   Constant fieldConstant = codegenBinding.constant();
   if (fieldConstant != Constant.NotAConstant) {
     if (!isThisReceiver) {
       this.receiver.generateCode(currentScope, codeStream, !isStatic);
       if (!isStatic) {
         codeStream.invokeObjectGetClass();
         codeStream.pop();
       }
     }
     if (valueRequired) {
       codeStream.generateConstant(fieldConstant, this.implicitConversion);
     }
     codeStream.recordPositionsFrom(pc, this.sourceStart);
     return;
   }
   if (valueRequired
       || (!isThisReceiver
           && currentScope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_4)
       || ((this.implicitConversion & TypeIds.UNBOXING) != 0)
       || (this.genericCast != null)) {
     this.receiver.generateCode(currentScope, codeStream, !isStatic);
     if ((this.bits & NeedReceiverGenericCast) != 0) {
       codeStream.checkcast(this.actualReceiverType);
     }
     pc = codeStream.position;
     if (codegenBinding.declaringClass == null) { // array length
       codeStream.arraylength();
       if (valueRequired) {
         codeStream.generateImplicitConversion(this.implicitConversion);
       } else {
         // could occur if !valueRequired but compliance >= 1.4
         codeStream.pop();
       }
     } else {
       if (this.syntheticAccessors == null
           || this.syntheticAccessors[FieldReference.READ] == null) {
         TypeBinding constantPoolDeclaringClass =
             CodeStream.getConstantPoolDeclaringClass(
                 currentScope,
                 codegenBinding,
                 this.actualReceiverType,
                 this.receiver.isImplicitThis());
         if (isStatic) {
           codeStream.fieldAccess(
               Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
         } else {
           codeStream.fieldAccess(
               Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
         }
       } else {
         codeStream.invoke(
             Opcodes.OPC_invokestatic,
             this.syntheticAccessors[FieldReference.READ],
             null /* default declaringClass */);
       }
       // required cast must occur even if no value is required
       if (this.genericCast != null) codeStream.checkcast(this.genericCast);
       if (valueRequired) {
         codeStream.generateImplicitConversion(this.implicitConversion);
       } else {
         boolean isUnboxing = (this.implicitConversion & TypeIds.UNBOXING) != 0;
         // conversion only generated if unboxing
         if (isUnboxing) codeStream.generateImplicitConversion(this.implicitConversion);
         switch (isUnboxing ? postConversionType(currentScope).id : codegenBinding.type.id) {
           case T_long:
           case T_double:
             codeStream.pop2();
             break;
           default:
             codeStream.pop();
         }
       }
     }
   } else {
     if (isThisReceiver) {
       if (isStatic) {
         // if no valueRequired, still need possible side-effects of <clinit> invocation, if field
         // belongs to different class
         if (this.binding.original().declaringClass != this.actualReceiverType.erasure()) {
           MethodBinding accessor =
               this.syntheticAccessors == null
                   ? null
                   : this.syntheticAccessors[FieldReference.READ];
           if (accessor == null) {
             TypeBinding constantPoolDeclaringClass =
                 CodeStream.getConstantPoolDeclaringClass(
                     currentScope,
                     codegenBinding,
                     this.actualReceiverType,
                     this.receiver.isImplicitThis());
             codeStream.fieldAccess(
                 Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
           } else {
             codeStream.invoke(
                 Opcodes.OPC_invokestatic, accessor, null /* default declaringClass */);
           }
           switch (codegenBinding.type.id) {
             case T_long:
             case T_double:
               codeStream.pop2();
               break;
             default:
               codeStream.pop();
           }
         }
       }
     } else {
       this.receiver.generateCode(currentScope, codeStream, !isStatic);
       if (!isStatic) {
         codeStream.invokeObjectGetClass(); // perform null check
         codeStream.pop();
       }
     }
   }
   codeStream.recordPositionsFrom(pc, this.sourceEnd);
 }
 public void generateCompoundAssignment(
     BlockScope currentScope,
     CodeStream codeStream,
     Expression expression,
     int operator,
     int assignmentImplicitConversion,
     boolean valueRequired) {
   boolean isStatic;
   // check if compound assignment is the only usage of a private field
   reportOnlyUselesslyReadPrivateField(currentScope, this.binding, valueRequired);
   FieldBinding codegenBinding = this.binding.original();
   this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
   if (isStatic) {
     if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
       TypeBinding constantPoolDeclaringClass =
           CodeStream.getConstantPoolDeclaringClass(
               currentScope,
               codegenBinding,
               this.actualReceiverType,
               this.receiver.isImplicitThis());
       codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
     } else {
       codeStream.invoke(
           Opcodes.OPC_invokestatic,
           this.syntheticAccessors[FieldReference.READ],
           null /* default declaringClass */);
     }
   } else {
     codeStream.dup();
     if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
       TypeBinding constantPoolDeclaringClass =
           CodeStream.getConstantPoolDeclaringClass(
               currentScope,
               codegenBinding,
               this.actualReceiverType,
               this.receiver.isImplicitThis());
       codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
     } else {
       codeStream.invoke(
           Opcodes.OPC_invokestatic,
           this.syntheticAccessors[FieldReference.READ],
           null /* default declaringClass */);
     }
   }
   int operationTypeID;
   switch (operationTypeID = (this.implicitConversion & TypeIds.IMPLICIT_CONVERSION_MASK) >> 4) {
     case T_JavaLangString:
     case T_JavaLangObject:
     case T_undefined:
       codeStream.generateStringConcatenationAppend(currentScope, null, expression);
       break;
     default:
       if (this.genericCast != null) codeStream.checkcast(this.genericCast);
       // promote the array reference to the suitable operation type
       codeStream.generateImplicitConversion(this.implicitConversion);
       // generate the increment value (will by itself  be promoted to the operation value)
       if (expression == IntLiteral.One) { // prefix operation
         codeStream.generateConstant(expression.constant, this.implicitConversion);
       } else {
         expression.generateCode(currentScope, codeStream, true);
       }
       // perform the operation
       codeStream.sendOperator(operator, operationTypeID);
       // cast the value back to the array reference type
       codeStream.generateImplicitConversion(assignmentImplicitConversion);
   }
   fieldStore(
       currentScope,
       codeStream,
       codegenBinding,
       this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE],
       this.actualReceiverType,
       this.receiver.isImplicitThis(),
       valueRequired);
   // no need for generic cast as value got dupped
 }
Beispiel #27
0
  /**
   * Try statement code generation with or without jsr bytecode use post 1.5 target level, cannot
   * use jsr bytecode, must instead inline finally block returnAddress is only allocated if jsr is
   * allowed
   */
  public void generateCode(BlockScope currentScope, CodeStream codeStream) {
    if ((bits & IsReachableMASK) == 0) {
      return;
    }
    // in case the labels needs to be reinitialized
    // when the code generation is restarted in wide mode
    if (this.anyExceptionLabelsCount > 0) {
      this.anyExceptionLabels = NO_EXCEPTION_HANDLER;
      this.anyExceptionLabelsCount = 0;
    }
    int pc = codeStream.position;
    final int NO_FINALLY = 0; // no finally block
    final int FINALLY_SUBROUTINE =
        1; // finally is generated as a subroutine (using jsr/ret bytecodes)
    final int FINALLY_DOES_NOT_COMPLETE =
        2; // non returning finally is optimized with only one instance of finally block
    final int FINALLY_MUST_BE_INLINED =
        3; // finally block must be inlined since cannot use jsr/ret bytecodes >1.5
    int finallyMode;
    if (subRoutineStartLabel == null) {
      finallyMode = NO_FINALLY;
    } else {
      if (this.isSubRoutineEscaping) {
        finallyMode = FINALLY_DOES_NOT_COMPLETE;
      } else if (scope.compilerOptions().inlineJsrBytecode) {
        finallyMode = FINALLY_MUST_BE_INLINED;
      } else {
        finallyMode = FINALLY_SUBROUTINE;
      }
    }
    boolean requiresNaturalExit = false;
    // preparing exception labels
    int maxCatches;
    ExceptionLabel[] exceptionLabels =
        new ExceptionLabel[maxCatches = catchArguments == null ? 0 : catchArguments.length];
    for (int i = 0; i < maxCatches; i++) {
      exceptionLabels[i] = new ExceptionLabel(codeStream, catchArguments[i].binding.type);
    }
    if (subRoutineStartLabel != null) {
      subRoutineStartLabel.initialize(codeStream);
      this.enterAnyExceptionHandler(codeStream);
    }
    // generate the try block
    tryBlock.generateCode(scope, codeStream);
    boolean tryBlockHasSomeCode = codeStream.position != pc;
    // flag telling if some bytecodes were issued inside the try block

    // place end positions of user-defined exception labels
    if (tryBlockHasSomeCode) {
      // natural exit may require subroutine invocation (if finally != null)
      Label naturalExitLabel = new Label(codeStream);
      if (!tryBlockExit) {
        int position = codeStream.position;
        switch (finallyMode) {
          case FINALLY_SUBROUTINE:
          case FINALLY_MUST_BE_INLINED:
            requiresNaturalExit = true;
            // fall through
          case NO_FINALLY:
            codeStream.goto_(naturalExitLabel);
            break;
          case FINALLY_DOES_NOT_COMPLETE:
            codeStream.goto_(subRoutineStartLabel);
            break;
        }
        codeStream.updateLastRecordedEndPC(tryBlock.scope, position);
        // goto is tagged as part of the try block
      }
      for (int i = 0; i < maxCatches; i++) {
        exceptionLabels[i].placeEnd();
      }
      /* generate sequence of handler, all starting by storing the TOS (exception
      thrown) into their own catch variables, the one specified in the source
      that must denote the handled exception.
      */
      if (catchArguments != null) {
        for (int i = 0; i < maxCatches; i++) {
          // May loose some local variable initializations : affecting the local variable attributes
          if (preTryInitStateIndex != -1) {
            codeStream.removeNotDefinitelyAssignedVariables(currentScope, preTryInitStateIndex);
          }
          exceptionLabels[i].place();
          codeStream.incrStackSize(1);
          // optimizing the case where the exception variable is not actually used
          LocalVariableBinding catchVar;
          int varPC = codeStream.position;
          if ((catchVar = catchArguments[i].binding).resolvedPosition != -1) {
            codeStream.store(catchVar, false);
            catchVar.recordInitializationStartPC(codeStream.position);
            codeStream.addVisibleLocalVariable(catchVar);
          } else {
            codeStream.pop();
          }
          codeStream.recordPositionsFrom(varPC, catchArguments[i].sourceStart);
          // Keep track of the pcs at diverging point for computing the local attribute
          // since not passing the catchScope, the block generation will exitUserScope(catchScope)
          catchBlocks[i].generateCode(scope, codeStream);
          if (!catchExits[i]) {
            switch (finallyMode) {
              case FINALLY_SUBROUTINE:
              case FINALLY_MUST_BE_INLINED:
                requiresNaturalExit = true;
                // fall through
              case NO_FINALLY:
                codeStream.goto_(naturalExitLabel);
                break;
              case FINALLY_DOES_NOT_COMPLETE:
                codeStream.goto_(subRoutineStartLabel);
                break;
            }
          }
        }
      }
      this.exitAnyExceptionHandler();
      // extra handler for trailing natural exit (will be fixed up later on when natural exit is
      // generated below)
      ExceptionLabel naturalExitExceptionHandler =
          finallyMode == FINALLY_SUBROUTINE && requiresNaturalExit
              ? new ExceptionLabel(codeStream, null)
              : null;

      // addition of a special handler so as to ensure that any uncaught exception (or exception
      // thrown
      // inside catch blocks) will run the finally block
      int finallySequenceStartPC = codeStream.position;
      if (subRoutineStartLabel != null) {
        this.placeAllAnyExceptionHandlers();
        if (naturalExitExceptionHandler != null) naturalExitExceptionHandler.place();

        if (preTryInitStateIndex != -1) {
          // reset initialization state, as for a normal catch block
          codeStream.removeNotDefinitelyAssignedVariables(currentScope, preTryInitStateIndex);
        }

        codeStream.incrStackSize(1);
        switch (finallyMode) {
          case FINALLY_SUBROUTINE:
            codeStream.store(anyExceptionVariable, false);
            codeStream.jsr(subRoutineStartLabel);
            codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
            int position = codeStream.position;
            codeStream.load(anyExceptionVariable);
            codeStream.athrow();
            codeStream.recordPositionsFrom(position, finallyBlock.sourceEnd);
            subRoutineStartLabel.place();
            codeStream.incrStackSize(1);
            position = codeStream.position;
            codeStream.store(returnAddressVariable, false);
            codeStream.recordPositionsFrom(position, finallyBlock.sourceStart);
            finallyBlock.generateCode(scope, codeStream);
            position = codeStream.position;
            codeStream.ret(returnAddressVariable.resolvedPosition);
            //						codeStream.updateLastRecordedEndPC(position);
            codeStream.recordPositionsFrom(position, finallyBlock.sourceEnd);
            // the ret bytecode is part of the subroutine
            break;
          case FINALLY_MUST_BE_INLINED:
            codeStream.store(anyExceptionVariable, false);
            codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
            this.finallyBlock.generateCode(currentScope, codeStream);
            position = codeStream.position;
            codeStream.load(anyExceptionVariable);
            codeStream.athrow();
            subRoutineStartLabel.place();
            codeStream.recordPositionsFrom(position, finallyBlock.sourceEnd);
            break;
          case FINALLY_DOES_NOT_COMPLETE:
            codeStream.pop();
            subRoutineStartLabel.place();
            codeStream.recordPositionsFrom(finallySequenceStartPC, finallyBlock.sourceStart);
            finallyBlock.generateCode(scope, codeStream);
            break;
        }
        // will naturally fall into subsequent code after subroutine invocation
        naturalExitLabel.place();
        if (requiresNaturalExit) {
          switch (finallyMode) {
            case FINALLY_SUBROUTINE:
              int position = codeStream.position;
              // fix up natural exit handler
              naturalExitExceptionHandler.placeStart();
              codeStream.jsr(subRoutineStartLabel);
              naturalExitExceptionHandler.placeEnd();
              codeStream.recordPositionsFrom(position, finallyBlock.sourceEnd);
              break;
            case FINALLY_MUST_BE_INLINED:
              // May loose some local variable initializations : affecting the local variable
              // attributes
              // needed since any exception handler got inlined subroutine
              if (preTryInitStateIndex != -1) {
                codeStream.removeNotDefinitelyAssignedVariables(currentScope, preTryInitStateIndex);
              }
              // entire sequence for finally is associated to finally block
              finallyBlock.generateCode(scope, codeStream);
              break;
            case FINALLY_DOES_NOT_COMPLETE:
              break;
          }
        }
      } else {
        // no subroutine, simply position end label (natural exit == end)
        naturalExitLabel.place();
      }
    } else {
      // try block had no effect, only generate the body of the finally block if any
      if (subRoutineStartLabel != null) {
        finallyBlock.generateCode(scope, codeStream);
      }
    }
    // May loose some local variable initializations : affecting the local variable attributes
    if (mergedInitStateIndex != -1) {
      codeStream.removeNotDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
      codeStream.addDefinitelyAssignedVariables(currentScope, mergedInitStateIndex);
    }
    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();
    }
  }
Beispiel #29
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);
  }
 public void generatePostIncrement(
     BlockScope currentScope,
     CodeStream codeStream,
     CompoundAssignment postIncrement,
     boolean valueRequired) {
   boolean isStatic;
   // check if postIncrement is the only usage of a private field
   reportOnlyUselesslyReadPrivateField(currentScope, this.binding, valueRequired);
   FieldBinding codegenBinding = this.binding.original();
   this.receiver.generateCode(currentScope, codeStream, !(isStatic = codegenBinding.isStatic()));
   if (isStatic) {
     if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
       TypeBinding constantPoolDeclaringClass =
           CodeStream.getConstantPoolDeclaringClass(
               currentScope,
               codegenBinding,
               this.actualReceiverType,
               this.receiver.isImplicitThis());
       codeStream.fieldAccess(Opcodes.OPC_getstatic, codegenBinding, constantPoolDeclaringClass);
     } else {
       codeStream.invoke(
           Opcodes.OPC_invokestatic,
           this.syntheticAccessors[FieldReference.READ],
           null /* default declaringClass */);
     }
   } else {
     codeStream.dup();
     if (this.syntheticAccessors == null || this.syntheticAccessors[FieldReference.READ] == null) {
       TypeBinding constantPoolDeclaringClass =
           CodeStream.getConstantPoolDeclaringClass(
               currentScope,
               codegenBinding,
               this.actualReceiverType,
               this.receiver.isImplicitThis());
       codeStream.fieldAccess(Opcodes.OPC_getfield, codegenBinding, constantPoolDeclaringClass);
     } else {
       codeStream.invoke(
           Opcodes.OPC_invokestatic,
           this.syntheticAccessors[FieldReference.READ],
           null /* default declaringClass */);
     }
   }
   TypeBinding operandType;
   if (this.genericCast != null) {
     codeStream.checkcast(this.genericCast);
     operandType = this.genericCast;
   } else {
     operandType = codegenBinding.type;
   }
   if (valueRequired) {
     if (isStatic) {
       switch (operandType.id) {
         case TypeIds.T_long:
         case TypeIds.T_double:
           codeStream.dup2();
           break;
         default:
           codeStream.dup();
           break;
       }
     } else { // Stack:  [owner][old field value]  ---> [old field value][owner][old field value]
       switch (operandType.id) {
         case TypeIds.T_long:
         case TypeIds.T_double:
           codeStream.dup2_x1();
           break;
         default:
           codeStream.dup_x1();
           break;
       }
     }
   }
   codeStream.generateImplicitConversion(this.implicitConversion);
   codeStream.generateConstant(postIncrement.expression.constant, this.implicitConversion);
   codeStream.sendOperator(
       postIncrement.operator, this.implicitConversion & TypeIds.COMPILE_TYPE_MASK);
   codeStream.generateImplicitConversion(postIncrement.preAssignImplicitConversion);
   fieldStore(
       currentScope,
       codeStream,
       codegenBinding,
       this.syntheticAccessors == null ? null : this.syntheticAccessors[FieldReference.WRITE],
       this.actualReceiverType,
       this.receiver.isImplicitThis(),
       false);
 }