コード例 #1
0
ファイル: FunctionCodegen.java プロジェクト: AlexJuca/kotlin
  @NotNull
  private static FrameMap createFrameMap(
      @NotNull GenerationState state,
      @NotNull FunctionDescriptor function,
      @NotNull JvmMethodSignature signature,
      boolean isStatic) {
    FrameMap frameMap = new FrameMap();
    if (!isStatic) {
      frameMap.enterTemp(OBJECT_TYPE);
    }

    for (JvmMethodParameterSignature parameter : signature.getValueParameters()) {
      if (parameter.getKind() == JvmMethodParameterKind.RECEIVER) {
        ReceiverParameterDescriptor receiverParameter = function.getExtensionReceiverParameter();
        if (receiverParameter != null) {
          frameMap.enter(receiverParameter, state.getTypeMapper().mapType(receiverParameter));
        }
      } else if (parameter.getKind() != JvmMethodParameterKind.VALUE) {
        frameMap.enterTemp(parameter.getAsmType());
      }
    }

    for (ValueParameterDescriptor parameter : function.getValueParameters()) {
      frameMap.enter(parameter, state.getTypeMapper().mapType(parameter));
    }

    return frameMap;
  }
コード例 #2
0
ファイル: FunctionCodegen.java プロジェクト: AlexJuca/kotlin
 private static boolean isMethodOfAny(@NotNull FunctionDescriptor descriptor) {
   String name = descriptor.getName().asString();
   List<ValueParameterDescriptor> parameters = descriptor.getValueParameters();
   if (parameters.isEmpty()) {
     return name.equals("hashCode") || name.equals("toString");
   } else if (parameters.size() == 1 && name.equals("equals")) {
     return isNullableAny(parameters.get(0).getType());
   }
   return false;
 }
コード例 #3
0
  private void generateParameterAnnotations(
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull MethodVisitor mv,
      @NotNull JvmMethodSignature jvmSignature) {
    Iterator<ValueParameterDescriptor> iterator =
        functionDescriptor.getValueParameters().iterator();
    List<JvmMethodParameterSignature> kotlinParameterTypes = jvmSignature.getValueParameters();

    for (int i = 0; i < kotlinParameterTypes.size(); i++) {
      JvmMethodParameterSignature parameterSignature = kotlinParameterTypes.get(i);
      JvmMethodParameterKind kind = parameterSignature.getKind();
      if (kind.isSkippedInGenericSignature()) {
        markEnumOrInnerConstructorParameterAsSynthetic(mv, i);
        continue;
      }

      if (kind == JvmMethodParameterKind.VALUE) {
        ValueParameterDescriptor parameter = iterator.next();
        if (parameter.getIndex() != i) {
          v.getSerializationBindings().put(INDEX_FOR_VALUE_PARAMETER, parameter, i);
        }
        AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, typeMapper);

        if (functionDescriptor instanceof PropertySetterDescriptor) {
          PropertyDescriptor propertyDescriptor =
              ((PropertySetterDescriptor) functionDescriptor).getCorrespondingProperty();
          Annotated targetedAnnotations =
              new AnnotatedWithOnlyTargetedAnnotations(propertyDescriptor);
          annotationCodegen.genAnnotations(
              targetedAnnotations, parameterSignature.getAsmType(), SETTER_PARAMETER);
        }

        if (functionDescriptor instanceof ConstructorDescriptor) {
          annotationCodegen.genAnnotations(
              parameter, parameterSignature.getAsmType(), CONSTRUCTOR_PARAMETER);
        } else {
          annotationCodegen.genAnnotations(parameter, parameterSignature.getAsmType());
        }
      } else if (kind == JvmMethodParameterKind.RECEIVER) {
        ReceiverParameterDescriptor receiver =
            ((functionDescriptor instanceof PropertyAccessorDescriptor)
                    ? ((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty()
                    : functionDescriptor)
                .getExtensionReceiverParameter();
        if (receiver != null) {
          AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, typeMapper);
          Annotated targetedAnnotations =
              new AnnotatedWithOnlyTargetedAnnotations(receiver.getType());
          annotationCodegen.genAnnotations(
              targetedAnnotations, parameterSignature.getAsmType(), RECEIVER);
        }
      }
    }
  }
コード例 #4
0
ファイル: FunctionCodegen.java プロジェクト: AlexJuca/kotlin
 private static boolean isDefaultNeeded(FunctionDescriptor functionDescriptor) {
   boolean needed = false;
   if (functionDescriptor != null) {
     for (ValueParameterDescriptor parameterDescriptor : functionDescriptor.getValueParameters()) {
       if (parameterDescriptor.declaresDefaultValue()) {
         needed = true;
         break;
       }
     }
   }
   return needed;
 }
コード例 #5
0
  @Override
  protected void generateBody() {
    FunctionDescriptor erasedInterfaceFunction;
    if (samType == null) {
      erasedInterfaceFunction = getErasedInvokeFunction(funDescriptor);
    } else {
      erasedInterfaceFunction = samType.getAbstractMethod().getOriginal();
    }

    generateBridge(
        typeMapper.mapSignature(erasedInterfaceFunction).getAsmMethod(),
        typeMapper.mapSignature(funDescriptor).getAsmMethod());

    functionCodegen.generateMethod(OtherOrigin(element, funDescriptor), funDescriptor, strategy);

    // TODO: rewrite cause ugly hack
    if (samType != null) {
      SimpleFunctionDescriptorImpl descriptorForBridges =
          SimpleFunctionDescriptorImpl.create(
              funDescriptor.getContainingDeclaration(),
              funDescriptor.getAnnotations(),
              erasedInterfaceFunction.getName(),
              CallableMemberDescriptor.Kind.DECLARATION,
              funDescriptor.getSource());

      descriptorForBridges.initialize(
          null,
          erasedInterfaceFunction.getDispatchReceiverParameter(),
          erasedInterfaceFunction.getTypeParameters(),
          erasedInterfaceFunction.getValueParameters(),
          erasedInterfaceFunction.getReturnType(),
          Modality.OPEN,
          erasedInterfaceFunction.getVisibility());

      descriptorForBridges.addOverriddenDescriptor(erasedInterfaceFunction);
      functionCodegen.generateBridges(descriptorForBridges);
    }

    this.constructor = generateConstructor(superClassAsmType);

    if (isConst(closure)) {
      generateConstInstance();
    }

    genClosureFields(closure, v, typeMapper);

    functionCodegen.generateDefaultIfNeeded(
        context.intoFunction(funDescriptor),
        funDescriptor,
        context.getContextKind(),
        DefaultParameterValueLoader.DEFAULT,
        null);
  }
コード例 #6
0
ファイル: FunctionCodegen.java プロジェクト: AlexJuca/kotlin
  private static void generateTypeCheckBarrierIfNeeded(
      @NotNull InstructionAdapter iv,
      @NotNull FunctionDescriptor descriptor,
      @NotNull Type returnType,
      @Nullable final Type delegateParameterType) {
    BuiltinMethodsWithSpecialGenericSignature.DefaultValue defaultValue =
        BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(
            descriptor);
    if (defaultValue == null) return;

    assert descriptor.getValueParameters().size() == 1
        : "Should be descriptor with one value parameter, but found: " + descriptor;

    boolean isCheckForAny =
        delegateParameterType == null || OBJECT_TYPE.equals(delegateParameterType);

    final KotlinType kotlinType = descriptor.getValueParameters().get(0).getType();

    if (isCheckForAny && TypeUtils.isNullableType(kotlinType)) return;

    iv.load(1, OBJECT_TYPE);

    Label afterBarrier = new Label();

    if (isCheckForAny) {
      assert !TypeUtils.isNullableType(kotlinType)
          : "Only bridges for not-nullable types are necessary";
      iv.ifnonnull(afterBarrier);
    } else {
      CodegenUtilKt.generateIsCheck(iv, kotlinType, boxType(delegateParameterType));
      iv.ifne(afterBarrier);
    }

    StackValue.constant(defaultValue.getValue(), returnType).put(returnType, iv);
    iv.areturn(returnType);

    iv.visitLabel(afterBarrier);
  }
コード例 #7
0
 @NotNull
 public static FunctionDescriptor getErasedInvokeFunction(
     @NotNull FunctionDescriptor elementDescriptor) {
   int arity = elementDescriptor.getValueParameters().size();
   ClassDescriptor elementClass =
       elementDescriptor.getExtensionReceiverParameter() == null
           ? getBuiltIns(elementDescriptor).getFunction(arity)
           : getBuiltIns(elementDescriptor).getExtensionFunction(arity);
   return elementClass
       .getDefaultType()
       .getMemberScope()
       .getFunctions(OperatorConventions.INVOKE)
       .iterator()
       .next();
 }
コード例 #8
0
  private void generateBridge(@NotNull Method bridge, @NotNull Method delegate) {
    if (bridge.equals(delegate)) return;

    MethodVisitor mv =
        v.newMethod(
            OtherOrigin(element, funDescriptor),
            ACC_PUBLIC | ACC_BRIDGE,
            bridge.getName(),
            bridge.getDescriptor(),
            null,
            ArrayUtil.EMPTY_STRING_ARRAY);

    if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;

    mv.visitCode();

    InstructionAdapter iv = new InstructionAdapter(mv);
    ImplementationBodyCodegen.markLineNumberForSyntheticFunction(
        DescriptorUtils.getParentOfType(funDescriptor, ClassDescriptor.class), iv);

    iv.load(0, asmType);

    ReceiverParameterDescriptor receiver = funDescriptor.getExtensionReceiverParameter();
    int count = 1;
    if (receiver != null) {
      StackValue.local(count, bridge.getArgumentTypes()[count - 1])
          .put(typeMapper.mapType(receiver.getType()), iv);
      count++;
    }

    List<ValueParameterDescriptor> params = funDescriptor.getValueParameters();
    for (ValueParameterDescriptor param : params) {
      StackValue.local(count, bridge.getArgumentTypes()[count - 1])
          .put(typeMapper.mapType(param.getType()), iv);
      count++;
    }

    iv.invokevirtual(
        asmType.getInternalName(), delegate.getName(), delegate.getDescriptor(), false);
    StackValue.onStack(delegate.getReturnType()).put(bridge.getReturnType(), iv);

    iv.areturn(bridge.getReturnType());

    FunctionCodegen.endVisit(mv, "bridge", element);
  }
コード例 #9
0
ファイル: FunctionCodegen.java プロジェクト: AlexJuca/kotlin
  private static void generateLocalVariableTable(
      @NotNull MethodVisitor mv,
      @NotNull JvmMethodSignature jvmMethodSignature,
      @NotNull FunctionDescriptor functionDescriptor,
      @Nullable Type thisType,
      @NotNull Label methodBegin,
      @NotNull Label methodEnd,
      @NotNull OwnerKind ownerKind) {
    Iterator<ValueParameterDescriptor> valueParameters =
        functionDescriptor.getValueParameters().iterator();
    List<JvmMethodParameterSignature> params = jvmMethodSignature.getValueParameters();
    int shift = 0;

    boolean isStatic = AsmUtil.isStaticMethod(ownerKind, functionDescriptor);
    if (!isStatic) {
      // add this
      if (thisType != null) {
        mv.visitLocalVariable(
            "this", thisType.getDescriptor(), null, methodBegin, methodEnd, shift);
      } else {
        // TODO: provide thisType for callable reference
      }
      shift++;
    }

    for (int i = 0; i < params.size(); i++) {
      JvmMethodParameterSignature param = params.get(i);
      JvmMethodParameterKind kind = param.getKind();
      String parameterName;

      if (kind == JvmMethodParameterKind.VALUE) {
        ValueParameterDescriptor parameter = valueParameters.next();
        parameterName = parameter.getName().asString();
      } else {
        String lowercaseKind = kind.name().toLowerCase();
        parameterName = needIndexForVar(kind) ? "$" + lowercaseKind + "$" + i : "$" + lowercaseKind;
      }

      Type type = param.getAsmType();
      mv.visitLocalVariable(
          parameterName, type.getDescriptor(), null, methodBegin, methodEnd, shift);
      shift += type.getSize();
    }
  }
コード例 #10
0
  @NotNull
  private Method generateConstructor(@NotNull Type superClassAsmType) {
    List<FieldInfo> args = calculateConstructorParameters(typeMapper, closure, asmType);

    Type[] argTypes = fieldListToTypeArray(args);

    Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
    MethodVisitor mv =
        v.newMethod(
            OtherOrigin(element, funDescriptor),
            visibilityFlag,
            "<init>",
            constructor.getDescriptor(),
            null,
            ArrayUtil.EMPTY_STRING_ARRAY);
    if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
      mv.visitCode();
      InstructionAdapter iv = new InstructionAdapter(mv);

      int k = 1;
      for (FieldInfo fieldInfo : args) {
        k = genAssignInstanceFieldFromParam(fieldInfo, k, iv);
      }

      iv.load(0, superClassAsmType);

      if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE)) {
        int arity = funDescriptor.getValueParameters().size();
        if (funDescriptor.getExtensionReceiverParameter() != null) arity++;
        if (funDescriptor.getDispatchReceiverParameter() != null) arity++;
        iv.iconst(arity);
        iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "(I)V", false);
      } else {
        iv.invokespecial(superClassAsmType.getInternalName(), "<init>", "()V", false);
      }

      iv.visitInsn(RETURN);

      FunctionCodegen.endVisit(iv, "constructor", element);
    }
    return constructor;
  }
コード例 #11
0
ファイル: FunctionCodegen.java プロジェクト: AlexJuca/kotlin
  public static void generateDefaultImplBody(
      @NotNull MethodContext methodContext,
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull MethodVisitor mv,
      @NotNull DefaultParameterValueLoader loadStrategy,
      @Nullable KtNamedFunction function,
      @NotNull MemberCodegen<?> parentCodegen,
      @NotNull Method defaultMethod) {
    GenerationState state = parentCodegen.state;
    JvmMethodSignature signature =
        state.getTypeMapper().mapSignature(functionDescriptor, methodContext.getContextKind());

    boolean isStatic = isStaticMethod(methodContext.getContextKind(), functionDescriptor);
    FrameMap frameMap = createFrameMap(state, functionDescriptor, signature, isStatic);

    ExpressionCodegen codegen =
        new ExpressionCodegen(
            mv, frameMap, signature.getReturnType(), methodContext, state, parentCodegen);

    CallGenerator generator =
        codegen.getOrCreateCallGeneratorForDefaultImplBody(functionDescriptor, function);

    InstructionAdapter iv = new InstructionAdapter(mv);
    genDefaultSuperCallCheckIfNeeded(iv, defaultMethod);

    loadExplicitArgumentsOnStack(OBJECT_TYPE, isStatic, signature, generator);

    List<JvmMethodParameterSignature> mappedParameters = signature.getValueParameters();
    int capturedArgumentsCount = 0;
    while (capturedArgumentsCount < mappedParameters.size()
        && mappedParameters.get(capturedArgumentsCount).getKind() != JvmMethodParameterKind.VALUE) {
      capturedArgumentsCount++;
    }

    int maskIndex = 0;
    List<ValueParameterDescriptor> valueParameters = functionDescriptor.getValueParameters();
    for (int index = 0; index < valueParameters.size(); index++) {
      if (index % Integer.SIZE == 0) {
        maskIndex = frameMap.enterTemp(Type.INT_TYPE);
      }
      ValueParameterDescriptor parameterDescriptor = valueParameters.get(index);
      Type type = mappedParameters.get(capturedArgumentsCount + index).getAsmType();

      int parameterIndex = frameMap.getIndex(parameterDescriptor);
      if (parameterDescriptor.declaresDefaultValue()) {
        iv.load(maskIndex, Type.INT_TYPE);
        iv.iconst(1 << (index % Integer.SIZE));
        iv.and(Type.INT_TYPE);
        Label loadArg = new Label();
        iv.ifeq(loadArg);

        StackValue.local(parameterIndex, type)
            .store(loadStrategy.genValue(parameterDescriptor, codegen), iv);

        iv.mark(loadArg);
      }

      generator.putValueIfNeeded(type, StackValue.local(parameterIndex, type));
    }

    CallableMethod method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false);

    generator.genCallWithoutAssertions(method, codegen);

    iv.areturn(signature.getReturnType());
  }