Ejemplo n.º 1
0
  void generateDefaultIfNeeded(
      @NotNull MethodContext owner,
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull OwnerKind kind,
      @NotNull DefaultParameterValueLoader loadStrategy,
      @Nullable KtNamedFunction function) {
    DeclarationDescriptor contextClass = owner.getContextDescriptor().getContainingDeclaration();

    if (kind != OwnerKind.DEFAULT_IMPLS && isInterface(contextClass)) {
      return;
    }

    if (!isDefaultNeeded(functionDescriptor)) {
      return;
    }

    int flags =
        getVisibilityAccessFlag(functionDescriptor)
            | getDeprecatedAccessFlag(functionDescriptor)
            | ACC_SYNTHETIC;
    if (!(functionDescriptor instanceof ConstructorDescriptor)) {
      flags |= ACC_STATIC | ACC_BRIDGE;
    }
    // $default methods are never private to be accessible from other class files (e.g. inner)
    // without the need of synthetic accessors
    flags &= ~ACC_PRIVATE;

    Method defaultMethod = typeMapper.mapDefaultMethod(functionDescriptor, kind);

    MethodVisitor mv =
        v.newMethod(
            JvmDeclarationOriginKt.Synthetic(function, functionDescriptor),
            flags,
            defaultMethod.getName(),
            defaultMethod.getDescriptor(),
            null,
            getThrownExceptions(functionDescriptor, typeMapper));

    // Only method annotations are copied to the $default method. Parameter annotations are not
    // copied until there are valid use cases;
    // enum constructors have two additional synthetic parameters which somewhat complicate this
    // task
    AnnotationCodegen.forMethod(mv, typeMapper)
        .genAnnotations(functionDescriptor, defaultMethod.getReturnType());

    if (state.getClassBuilderMode() == ClassBuilderMode.FULL) {
      if (this.owner instanceof MultifileClassFacadeContext) {
        mv.visitCode();
        generateFacadeDelegateMethodBody(
            mv, defaultMethod, (MultifileClassFacadeContext) this.owner);
        endVisit(mv, "default method delegation", getSourceFromDescriptor(functionDescriptor));
      } else {
        mv.visitCode();
        generateDefaultImplBody(
            owner, functionDescriptor, mv, loadStrategy, function, memberCodegen, defaultMethod);
        endVisit(mv, "default method", getSourceFromDescriptor(functionDescriptor));
      }
    }
  }
Ejemplo n.º 2
0
  public static void generateMethodBody(
      @NotNull MethodVisitor mv,
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull MethodContext context,
      @NotNull JvmMethodSignature signature,
      @NotNull FunctionGenerationStrategy strategy,
      @NotNull MemberCodegen<?> parentCodegen) {
    mv.visitCode();

    Label methodBegin = new Label();
    mv.visitLabel(methodBegin);

    JetTypeMapper typeMapper = parentCodegen.typeMapper;

    Label methodEnd;
    if (context.getParentContext() instanceof DelegatingFacadeContext) {
      generateFacadeDelegateMethodBody(
          mv, signature.getAsmMethod(), (DelegatingFacadeContext) context.getParentContext());
      methodEnd = new Label();
    } else {
      FrameMap frameMap =
          createFrameMap(
              parentCodegen.state,
              functionDescriptor,
              signature,
              isStaticMethod(context.getContextKind(), functionDescriptor));

      Label methodEntry = new Label();
      mv.visitLabel(methodEntry);
      context.setMethodStartLabel(methodEntry);

      if (!JetTypeMapper.isAccessor(functionDescriptor)) {
        genNotNullAssertionsForParameters(
            new InstructionAdapter(mv), parentCodegen.state, functionDescriptor, frameMap);
      }
      methodEnd = new Label();
      context.setMethodEndLabel(methodEnd);
      strategy.generateBody(mv, frameMap, signature, context, parentCodegen);
    }

    mv.visitLabel(methodEnd);

    Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper);
    generateLocalVariableTable(
        mv,
        signature,
        functionDescriptor,
        thisType,
        methodBegin,
        methodEnd,
        context.getContextKind());
  }
Ejemplo n.º 3
0
  public static void generateMethodBody(
      @NotNull MethodVisitor mv,
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull MethodContext context,
      @NotNull JvmMethodSignature signature,
      @NotNull FunctionGenerationStrategy strategy,
      @NotNull MemberCodegen<?> parentCodegen) {
    mv.visitCode();

    Label methodBegin = new Label();
    mv.visitLabel(methodBegin);

    JetTypeMapper typeMapper = parentCodegen.typeMapper;
    if (BuiltinSpecialBridgesUtil.shouldHaveTypeSafeBarrier(
        functionDescriptor, getSignatureMapper(typeMapper))) {
      generateTypeCheckBarrierIfNeeded(
          new InstructionAdapter(mv),
          functionDescriptor,
          signature.getReturnType(),
          /* delegateParameterType = */ null);
    }

    Label methodEnd;

    int functionFakeIndex = -1;
    int lambdaFakeIndex = -1;

    if (context.getParentContext() instanceof MultifileClassFacadeContext) {
      generateFacadeDelegateMethodBody(
          mv, signature.getAsmMethod(), (MultifileClassFacadeContext) context.getParentContext());
      methodEnd = new Label();
    } else {
      FrameMap frameMap =
          createFrameMap(
              parentCodegen.state,
              functionDescriptor,
              signature,
              isStaticMethod(context.getContextKind(), functionDescriptor));
      if (context.isInlineMethodContext()) {
        functionFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
      }

      if (context instanceof InlineLambdaContext) {
        lambdaFakeIndex = frameMap.enterTemp(Type.INT_TYPE);
      }

      Label methodEntry = new Label();
      mv.visitLabel(methodEntry);
      context.setMethodStartLabel(methodEntry);

      if (!JetTypeMapper.isAccessor(functionDescriptor)) {
        genNotNullAssertionsForParameters(
            new InstructionAdapter(mv), parentCodegen.state, functionDescriptor, frameMap);
      }
      methodEnd = new Label();
      context.setMethodEndLabel(methodEnd);
      strategy.generateBody(mv, frameMap, signature, context, parentCodegen);
    }

    mv.visitLabel(methodEnd);

    Type thisType = getThisTypeForFunction(functionDescriptor, context, typeMapper);
    generateLocalVariableTable(
        mv,
        signature,
        functionDescriptor,
        thisType,
        methodBegin,
        methodEnd,
        context.getContextKind());

    if (context.isInlineMethodContext() && functionFakeIndex != -1) {
      mv.visitLocalVariable(
          JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION
              + functionDescriptor.getName().asString(),
          Type.INT_TYPE.getDescriptor(),
          null,
          methodBegin,
          methodEnd,
          functionFakeIndex);
    }

    if (context instanceof InlineLambdaContext && thisType != null && lambdaFakeIndex != -1) {
      String name = thisType.getClassName();
      int indexOfLambdaOrdinal = name.lastIndexOf("$");
      if (indexOfLambdaOrdinal > 0) {
        int lambdaOrdinal = Integer.parseInt(name.substring(indexOfLambdaOrdinal + 1));
        mv.visitLocalVariable(
            JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT + lambdaOrdinal,
            Type.INT_TYPE.getDescriptor(),
            null,
            methodBegin,
            methodEnd,
            lambdaFakeIndex);
      }
    }
  }