예제 #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));
      }
    }
  }
예제 #2
0
  @NotNull
  private SMAPAndMethodNode createMethodNode(boolean callDefault)
      throws ClassNotFoundException, IOException {
    JvmMethodSignature jvmSignature =
        typeMapper.mapSignature(functionDescriptor, context.getContextKind());

    Method asmMethod;
    if (callDefault) {
      asmMethod = typeMapper.mapDefaultMethod(functionDescriptor, context.getContextKind());
    } else {
      asmMethod = jvmSignature.getAsmMethod();
    }

    SMAPAndMethodNode nodeAndSMAP;
    if (functionDescriptor instanceof DeserializedSimpleFunctionDescriptor) {
      JetTypeMapper.ContainingClassesInfo containingClasses =
          typeMapper.getContainingClassesForDeserializedCallable(
              (DeserializedSimpleFunctionDescriptor) functionDescriptor);

      VirtualFile file =
          InlineCodegenUtil.getVirtualFileForCallable(containingClasses.getImplClassId(), state);
      nodeAndSMAP =
          InlineCodegenUtil.getMethodNode(
              file.contentsToByteArray(),
              asmMethod.getName(),
              asmMethod.getDescriptor(),
              containingClasses.getFacadeClassId());

      if (nodeAndSMAP == null) {
        throw new RuntimeException(
            "Couldn't obtain compiled function body for " + descriptorName(functionDescriptor));
      }
    } else {
      PsiElement element = DescriptorToSourceUtils.descriptorToDeclaration(functionDescriptor);

      if (element == null || !(element instanceof JetNamedFunction)) {
        throw new RuntimeException(
            "Couldn't find declaration for function " + descriptorName(functionDescriptor));
      }
      JetNamedFunction inliningFunction = (JetNamedFunction) element;

      MethodNode node =
          new MethodNode(
              InlineCodegenUtil.API,
              getMethodAsmFlags(functionDescriptor, context.getContextKind())
                  | (callDefault ? Opcodes.ACC_STATIC : 0),
              asmMethod.getName(),
              asmMethod.getDescriptor(),
              jvmSignature.getGenericsSignature(),
              null);

      // for maxLocals calculation
      MethodVisitor maxCalcAdapter = InlineCodegenUtil.wrapWithMaxLocalCalc(node);
      MethodContext methodContext = context.getParentContext().intoFunction(functionDescriptor);

      SMAP smap;
      if (callDefault) {
        Type implementationOwner = typeMapper.mapOwner(functionDescriptor);
        FakeMemberCodegen parentCodegen =
            new FakeMemberCodegen(
                codegen.getParentCodegen(),
                inliningFunction,
                (FieldOwnerContext) methodContext.getParentContext(),
                implementationOwner.getInternalName());
        FunctionCodegen.generateDefaultImplBody(
            methodContext,
            functionDescriptor,
            maxCalcAdapter,
            DefaultParameterValueLoader.DEFAULT,
            inliningFunction,
            parentCodegen);
        smap =
            createSMAPWithDefaultMapping(
                inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
      } else {
        smap =
            generateMethodBody(
                maxCalcAdapter,
                functionDescriptor,
                methodContext,
                inliningFunction,
                jvmSignature,
                false);
      }

      nodeAndSMAP = new SMAPAndMethodNode(node, smap);
      maxCalcAdapter.visitMaxs(-1, -1);
      maxCalcAdapter.visitEnd();
    }
    return nodeAndSMAP;
  }