Пример #1
0
  /**
   * 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
  }
Пример #2
0
 /**
  * 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;
   // generate receiver/enclosing instance access
   MethodBinding codegenBinding =
       this.binding instanceof PolymorphicMethodBinding ? this.binding : this.binding.original();
   boolean isStatic = codegenBinding.isStatic();
   if (isStatic) {
     this.receiver.generateCode(currentScope, codeStream, false);
   } else if ((this.bits & ASTNode.DepthMASK) != 0
       && this.receiver.isImplicitThis()) { // outer access ?
     // outer method can be reached through emulation if implicit access
     ReferenceBinding targetType =
         currentScope
             .enclosingSourceType()
             .enclosingTypeAt((this.bits & ASTNode.DepthMASK) >> ASTNode.DepthSHIFT);
     Object[] path =
         currentScope.getEmulationPath(
             targetType, true /*only exact match*/, false /*consider enclosing arg*/);
     codeStream.generateOuterAccess(path, this, targetType, currentScope);
   } else {
     this.receiver.generateCode(currentScope, codeStream, true);
     if ((this.bits & NeedReceiverGenericCast) != 0) {
       codeStream.checkcast(this.actualReceiverType);
     }
   }
   codeStream.recordPositionsFrom(pc, this.sourceStart);
   // generate arguments
   generateArguments(this.binding, this.arguments, currentScope, codeStream);
   pc = codeStream.position;
   // actual message invocation
   if (this.syntheticAccessor == null) {
     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.invoke(
         Opcodes.OPC_invokestatic, this.syntheticAccessor, null /* default declaringClass */);
   }
   // 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
 }