Example #1
0
  private void generateBridge(
      @Nullable PsiElement origin,
      @NotNull FunctionDescriptor descriptor,
      @NotNull Method bridge,
      @NotNull Method delegateTo,
      boolean isSpecialBridge,
      boolean isStubDeclarationWithDelegationToSuper) {
    boolean isSpecialOrDelegationToSuper =
        isSpecialBridge || isStubDeclarationWithDelegationToSuper;
    int flags =
        ACC_PUBLIC
            | ACC_BRIDGE
            | (!isSpecialOrDelegationToSuper ? ACC_SYNTHETIC : 0)
            | (isSpecialBridge ? ACC_FINAL : 0); // TODO.

    MethodVisitor mv =
        v.newMethod(
            JvmDeclarationOriginKt.Bridge(descriptor, origin),
            flags,
            bridge.getName(),
            bridge.getDescriptor(),
            null,
            null);
    if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;

    mv.visitCode();

    Type[] argTypes = bridge.getArgumentTypes();
    Type[] originalArgTypes = delegateTo.getArgumentTypes();

    InstructionAdapter iv = new InstructionAdapter(mv);
    MemberCodegen.markLineNumberForDescriptor(owner.getThisDescriptor(), iv);

    if (delegateTo.getArgumentTypes().length == 1 && isSpecialBridge) {
      generateTypeCheckBarrierIfNeeded(
          iv, descriptor, bridge.getReturnType(), delegateTo.getArgumentTypes()[0]);
    }

    iv.load(0, OBJECT_TYPE);
    for (int i = 0, reg = 1; i < argTypes.length; i++) {
      StackValue.local(reg, argTypes[i]).put(originalArgTypes[i], iv);
      //noinspection AssignmentToForLoopParameter
      reg += argTypes[i].getSize();
    }

    if (isStubDeclarationWithDelegationToSuper) {
      ClassDescriptor parentClass =
          getSuperClassDescriptor((ClassDescriptor) descriptor.getContainingDeclaration());
      assert parentClass != null;
      String parentInternalName = typeMapper.mapClass(parentClass).getInternalName();
      iv.invokespecial(parentInternalName, delegateTo.getName(), delegateTo.getDescriptor());
    } else {
      iv.invokevirtual(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
    }

    StackValue.coerce(delegateTo.getReturnType(), bridge.getReturnType(), iv);
    iv.areturn(bridge.getReturnType());

    endVisit(mv, "bridge method", origin);
  }
  private ClassDescriptor recordClassForFunction(FunctionDescriptor funDescriptor) {
    ClassDescriptor classDescriptor;
    int arity = funDescriptor.getValueParameters().size();

    classDescriptor =
        new ClassDescriptorImpl(
            funDescriptor.getContainingDeclaration(),
            Collections.<AnnotationDescriptor>emptyList(),
            Modality.FINAL,
            Name.special("<closure>"));
    ((ClassDescriptorImpl) classDescriptor)
        .initialize(
            false,
            Collections.<TypeParameterDescriptor>emptyList(),
            Collections.singleton(
                (funDescriptor.getReceiverParameter().exists()
                        ? JetStandardClasses.getReceiverFunction(arity)
                        : JetStandardClasses.getFunction(arity))
                    .getDefaultType()),
            JetScope.EMPTY,
            Collections.<ConstructorDescriptor>emptySet(),
            null);

    assert PsiCodegenPredictor.checkPredictedClassNameForFun(
        bindingContext, funDescriptor, classDescriptor);
    bindingTrace.record(CLASS_FOR_FUNCTION, funDescriptor, classDescriptor);
    return classDescriptor;
  }
  public boolean isMain(@NotNull JetNamedFunction function) {
    if (!"main".equals(function.getName())) return false;

    FunctionDescriptor functionDescriptor = getFunctionDescriptor.fun(function);
    List<ValueParameterDescriptor> parameters = functionDescriptor.getValueParameters();
    if (parameters.size() != 1) return false;

    ValueParameterDescriptor parameter = parameters.get(0);
    JetType parameterType = parameter.getType();
    if (!KotlinBuiltIns.isArray(parameterType)) return false;

    List<TypeProjection> typeArguments = parameterType.getArguments();
    if (typeArguments.size() != 1) return false;

    JetType typeArgument = typeArguments.get(0).getType();
    if (!JetTypeChecker.DEFAULT.equalTypes(
        typeArgument, getBuiltIns(functionDescriptor).getStringType())) return false;

    if (DescriptorUtils.isTopLevelDeclaration(functionDescriptor)) return true;

    DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
    return containingDeclaration instanceof ClassDescriptor
        && ((ClassDescriptor) containingDeclaration).getKind().isSingleton()
        && AnnotationsPackage.hasPlatformStaticAnnotation(functionDescriptor);
  }
Example #4
0
  public static int getMethodAsmFlags(FunctionDescriptor functionDescriptor, OwnerKind kind) {
    int flags = getCommonCallableFlags(functionDescriptor);

    if (functionDescriptor.getModality() == Modality.FINAL
        && !(functionDescriptor instanceof ConstructorDescriptor)) {
      DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
      if (!(containingDeclaration instanceof ClassDescriptor)
          || ((ClassDescriptor) containingDeclaration).getKind() != ClassKind.TRAIT) {
        flags |= ACC_FINAL;
      }
    }

    if (isStaticMethod(kind, functionDescriptor)) {
      flags |= ACC_STATIC;
    }

    if (isAbstractMethod(functionDescriptor, kind)) {
      flags |= ACC_ABSTRACT;
    }

    if (JetTypeMapper.isAccessor(functionDescriptor)) {
      flags |= ACC_SYNTHETIC;
    }

    return flags;
  }
Example #5
0
 public void genDelegate(
     @NotNull FunctionDescriptor functionDescriptor,
     FunctionDescriptor overriddenDescriptor,
     StackValue field) {
   genDelegate(
       functionDescriptor,
       overriddenDescriptor.getOriginal(),
       (ClassDescriptor) overriddenDescriptor.getContainingDeclaration(),
       field);
 }
Example #6
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);
  }
 @NotNull
 @Override
 public String getText() {
   if (functionsToAdd.size() == 1) {
     FunctionDescriptor newFunction = functionsToAdd.get(0);
     ClassDescriptor supertype = (ClassDescriptor) newFunction.getContainingDeclaration();
     return JetBundle.message(
         "add.function.to.type.action.single",
         IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(newFunction),
         supertype.getName().toString());
   } else {
     return JetBundle.message("add.function.to.supertype.action.multiple");
   }
 }
  @NotNull
  private static FunctionDescriptor substituteSuperFunction(
      @NotNull Map<ClassDescriptor, JetType> superclassToSupertype,
      @NotNull FunctionDescriptor superFun) {
    DeclarationDescriptor superFunContainer = superFun.getContainingDeclaration();
    assert superFunContainer instanceof ClassDescriptor : superFunContainer;

    JetType supertype = superclassToSupertype.get(superFunContainer);
    assert supertype != null : "Couldn't find super type for super function: " + superFun;
    TypeSubstitutor supertypeSubstitutor = TypeSubstitutor.create(supertype);

    FunctionDescriptor substitutedSuperFun = superFun.substitute(supertypeSubstitutor);
    assert substitutedSuperFun != null;
    return substitutedSuperFun;
  }
  private static List<FunctionDescriptor> generateFunctionsToAdd(JetNamedFunction functionElement) {
    FunctionDescriptor functionDescriptor =
        (FunctionDescriptor) ResolvePackage.resolveToDescriptor(functionElement);

    DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
    if (!(containingDeclaration instanceof ClassDescriptor)) return Collections.emptyList();

    List<FunctionDescriptor> functions = Lists.newArrayList();
    ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
    // TODO: filter out impossible supertypes (for example when argument's type isn't visible in a
    // superclass).
    for (ClassDescriptor supertypeDescriptor : getSupertypes(classDescriptor)) {
      if (KotlinBuiltIns.isAnyOrNullableAny(supertypeDescriptor.getDefaultType())) continue;
      functions.add(generateFunctionSignatureForType(functionDescriptor, supertypeDescriptor));
    }
    return functions;
  }
Example #10
0
  private static void equipFunctionReferenceWithReflection(
      @NotNull InstructionAdapter v, @NotNull FunctionDescriptor target) {
    DeclarationDescriptor container = target.getContainingDeclaration();

    Type type;
    if (container instanceof PackageFragmentDescriptor) {
      type =
          target.getExtensionReceiverParameter() != null
              ? K_TOP_LEVEL_EXTENSION_FUNCTION
              : K_TOP_LEVEL_FUNCTION;
    } else if (container instanceof ClassDescriptor) {
      type = K_MEMBER_FUNCTION;
    } else {
      type = K_LOCAL_FUNCTION;
    }

    Method method = method("function", K_FUNCTION, FUNCTION_REFERENCE);
    v.invokestatic(REFLECTION, method.getName(), method.getDescriptor(), false);
    StackValue.coerce(K_FUNCTION, type, v);
  }
  @Override
  public void visitNamedFunction(JetNamedFunction function) {
    FunctionDescriptor functionDescriptor =
        (FunctionDescriptor) bindingContext.get(DECLARATION_TO_DESCRIPTOR, function);
    // working around a problem with shallow analysis
    if (functionDescriptor == null) return;
    DeclarationDescriptor containingDeclaration = functionDescriptor.getContainingDeclaration();
    if (containingDeclaration instanceof ClassDescriptor) {
      nameStack.push(peekFromStack(nameStack) + '$' + function.getName());
      super.visitNamedFunction(function);
      nameStack.pop();
    } else if (containingDeclaration instanceof NamespaceDescriptor) {
      String peek = peekFromStack(nameStack);
      if (peek.isEmpty()) {
        peek = JvmAbi.PACKAGE_CLASS;
      } else {
        peek += "/" + JvmAbi.PACKAGE_CLASS;
      }
      nameStack.push(peek + '$' + function.getName());
      super.visitNamedFunction(function);
      nameStack.pop();
    } else {
      String name = inventAnonymousClassName(function);
      ClassDescriptor classDescriptor = recordClassForFunction(functionDescriptor);
      recordClosure(
          bindingTrace,
          function,
          classDescriptor,
          peekFromStack(classStack),
          JvmClassName.byInternalName(name),
          true);

      classStack.push(classDescriptor);
      nameStack.push(name);
      super.visitNamedFunction(function);
      nameStack.pop();
      classStack.pop();
    }
  }
Example #12
0
  public void generateBridges(@NotNull FunctionDescriptor descriptor) {
    if (descriptor instanceof ConstructorDescriptor) return;
    if (owner.getContextKind() == OwnerKind.DEFAULT_IMPLS) return;
    if (isInterface(descriptor.getContainingDeclaration())) return;

    // equals(Any?), hashCode(), toString() never need bridges
    if (isMethodOfAny(descriptor)) return;

    // If the function doesn't have a physical declaration among super-functions, it's a SAM adapter
    // or alike and doesn't need bridges
    if (CallResolverUtilKt.isOrOverridesSynthesized(descriptor)) return;

    boolean isSpecial =
        SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor) != null;

    Set<Bridge<Method>> bridgesToGenerate;
    if (!isSpecial) {
      bridgesToGenerate =
          ImplKt.generateBridgesForFunctionDescriptor(descriptor, getSignatureMapper(typeMapper));
      if (!bridgesToGenerate.isEmpty()) {
        PsiElement origin =
            descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
        boolean isSpecialBridge =
            BuiltinMethodsWithSpecialGenericSignature
                    .getOverriddenBuiltinFunctionWithErasedValueParametersInJava(descriptor)
                != null;

        for (Bridge<Method> bridge : bridgesToGenerate) {
          generateBridge(
              origin, descriptor, bridge.getFrom(), bridge.getTo(), isSpecialBridge, false);
        }
      }
    } else {
      Set<BridgeForBuiltinSpecial<Method>> specials =
          BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
              descriptor, getSignatureMapper(typeMapper));

      if (!specials.isEmpty()) {
        PsiElement origin =
            descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
        for (BridgeForBuiltinSpecial<Method> bridge : specials) {
          generateBridge(
              origin,
              descriptor,
              bridge.getFrom(),
              bridge.getTo(),
              bridge.isSpecial(),
              bridge.isDelegateToSuper());
        }
      }

      if (!descriptor.getKind().isReal()
          && isAbstractMethod(descriptor, OwnerKind.IMPLEMENTATION)) {
        CallableDescriptor overridden =
            SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor);
        assert overridden != null;

        Method method = typeMapper.mapSignature(descriptor).getAsmMethod();
        int flags = ACC_ABSTRACT | getVisibilityAccessFlag(descriptor);
        v.newMethod(
            JvmDeclarationOriginKt.OtherOrigin(overridden),
            flags,
            method.getName(),
            method.getDescriptor(),
            null,
            null);
      }
    }
  }
Example #13
0
  public void generateMethod(
      @NotNull JvmDeclarationOrigin origin,
      @NotNull FunctionDescriptor functionDescriptor,
      @NotNull MethodContext methodContext,
      @NotNull FunctionGenerationStrategy strategy) {
    OwnerKind contextKind = methodContext.getContextKind();
    if (isInterface(functionDescriptor.getContainingDeclaration())
        && functionDescriptor.getVisibility() == Visibilities.PRIVATE
        && contextKind != OwnerKind.DEFAULT_IMPLS) {
      return;
    }

    JvmMethodSignature jvmSignature = typeMapper.mapSignature(functionDescriptor, contextKind);
    Method asmMethod = jvmSignature.getAsmMethod();

    int flags = getMethodAsmFlags(functionDescriptor, contextKind);
    boolean isNative = NativeKt.hasNativeAnnotation(functionDescriptor);

    if (isNative && owner instanceof MultifileClassFacadeContext) {
      // Native methods are only defined in facades and do not need package part implementations
      return;
    }
    MethodVisitor mv =
        v.newMethod(
            origin,
            flags,
            asmMethod.getName(),
            asmMethod.getDescriptor(),
            jvmSignature.getGenericsSignature(),
            getThrownExceptions(functionDescriptor, typeMapper));

    if (CodegenContextUtil.isImplClassOwner(owner)) {
      v.getSerializationBindings().put(METHOD_FOR_FUNCTION, functionDescriptor, asmMethod);
    }

    generateMethodAnnotations(functionDescriptor, asmMethod, mv);

    generateParameterAnnotations(
        functionDescriptor, mv, typeMapper.mapSignature(functionDescriptor));

    generateBridges(functionDescriptor);

    boolean staticInCompanionObject =
        AnnotationUtilKt.isPlatformStaticInCompanionObject(functionDescriptor);
    if (staticInCompanionObject) {
      ImplementationBodyCodegen parentBodyCodegen =
          (ImplementationBodyCodegen) memberCodegen.getParentCodegen();
      parentBodyCodegen.addAdditionalTask(
          new JvmStaticGenerator(functionDescriptor, origin, state));
    }

    if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES
        || isAbstractMethod(functionDescriptor, contextKind)) {
      generateLocalVariableTable(
          mv,
          jvmSignature,
          functionDescriptor,
          getThisTypeForFunction(functionDescriptor, methodContext, typeMapper),
          new Label(),
          new Label(),
          contextKind);

      mv.visitEnd();
      return;
    }

    if (!isNative) {
      generateMethodBody(
          mv, functionDescriptor, methodContext, jvmSignature, strategy, memberCodegen);
    } else if (staticInCompanionObject) {
      // native @JvmStatic foo() in companion object should delegate to the static native function
      // moved to the outer class
      mv.visitCode();
      FunctionDescriptor staticFunctionDescriptor =
          JvmStaticGenerator.createStaticFunctionDescriptor(functionDescriptor);
      JvmMethodSignature jvmMethodSignature =
          typeMapper.mapSignature(
              memberCodegen.getContext().accessibleDescriptor(staticFunctionDescriptor, null));
      Type owningType =
          typeMapper.mapClass(
              (ClassifierDescriptor) staticFunctionDescriptor.getContainingDeclaration());
      generateDelegateToMethodBody(
          false, mv, jvmMethodSignature.getAsmMethod(), owningType.getInternalName());
    }

    endVisit(mv, null, origin.getElement());
  }
Example #14
0
 public static boolean isAbstractMethod(FunctionDescriptor functionDescriptor, OwnerKind kind) {
   return (functionDescriptor.getModality() == Modality.ABSTRACT
           || isInterface(functionDescriptor.getContainingDeclaration()))
       && !isStaticMethod(kind, functionDescriptor);
 }