Exemplo n.º 1
0
  public InlineCodegen(
      @NotNull ExpressionCodegen codegen,
      @NotNull GenerationState state,
      @NotNull SimpleFunctionDescriptor functionDescriptor,
      @NotNull JetElement callElement,
      @Nullable ReifiedTypeParameterMappings typeParameterMappings) {
    assert InlineUtil.isInline(functionDescriptor)
        : "InlineCodegen could inline only inline function: " + functionDescriptor;

    this.state = state;
    this.typeMapper = state.getTypeMapper();
    this.codegen = codegen;
    this.callElement = callElement;
    this.functionDescriptor = functionDescriptor.getOriginal();

    reifiedTypeInliner = new ReifiedTypeInliner(typeParameterMappings);

    initialFrameSize = codegen.getFrameMap().getCurrentSize();

    context = (MethodContext) getContext(functionDescriptor, state);
    jvmSignature = typeMapper.mapSignature(functionDescriptor, context.getContextKind());

    // TODO: implement AS_FUNCTION inline strategy
    InlineStrategy inlineStrategy = InlineUtil.getInlineStrategy(functionDescriptor);
    this.asFunctionInline = false;

    isSameModule =
        JvmCodegenUtil.isCallInsideSameModuleAsDeclared(
            functionDescriptor, codegen.getContext(), state.getOutDirectory());

    sourceMapper = codegen.getParentCodegen().getOrCreateSourceMapper();
    reportIncrementalInfo(
        functionDescriptor, codegen.getContext().getFunctionDescriptor().getOriginal());
  }
Exemplo n.º 2
0
  private SMAPAndMethodNode generateLambdaBody(LambdaInfo info) {
    JetExpression declaration = info.getFunctionWithBodyOrCallableReference();
    FunctionDescriptor descriptor = info.getFunctionDescriptor();

    MethodContext parentContext = codegen.getContext();

    MethodContext context =
        parentContext.intoClosure(descriptor, codegen, typeMapper).intoInlinedLambda(descriptor);

    JvmMethodSignature jvmMethodSignature = typeMapper.mapSignature(descriptor);
    Method asmMethod = jvmMethodSignature.getAsmMethod();
    MethodNode methodNode =
        new MethodNode(
            InlineCodegenUtil.API,
            getMethodAsmFlags(descriptor, context.getContextKind()),
            asmMethod.getName(),
            asmMethod.getDescriptor(),
            jvmMethodSignature.getGenericsSignature(),
            null);

    MethodVisitor adapter = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode);

    SMAP smap =
        generateMethodBody(adapter, descriptor, context, declaration, jvmMethodSignature, true);
    adapter.visitMaxs(-1, -1);
    return new SMAPAndMethodNode(methodNode, smap);
  }
Exemplo n.º 3
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);
      }
    }
  }
Exemplo n.º 4
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;
  }
Exemplo n.º 5
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());
  }