コード例 #1
0
ファイル: InlineCodegen.java プロジェクト: grigala/kotlin
  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);
  }
コード例 #2
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;
  }
コード例 #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
  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());
  }
コード例 #5
0
ファイル: InlineCodegen.java プロジェクト: grigala/kotlin
  private void reportIncrementalInfo(
      @NotNull FunctionDescriptor sourceDescriptor, @NotNull FunctionDescriptor targetDescriptor) {
    IncrementalCompilationComponents incrementalCompilationComponents =
        state.getIncrementalCompilationComponents();
    TargetId targetId = state.getTargetId();

    if (incrementalCompilationComponents == null || targetId == null) return;

    IncrementalCache incrementalCache =
        incrementalCompilationComponents.getIncrementalCache(targetId);
    String sourceFile = getClassFilePath(sourceDescriptor, incrementalCache);
    String targetFile = getSourceFilePath(targetDescriptor);
    incrementalCache.registerInline(sourceFile, jvmSignature.toString(), targetFile);
  }
コード例 #6
0
ファイル: InlineCodegen.java プロジェクト: grigala/kotlin
  @Override
  public void putHiddenParams() {
    List<JvmMethodParameterSignature> valueParameters = jvmSignature.getValueParameters();

    if (!isStaticMethod(functionDescriptor, context)) {
      invocationParamBuilder.addNextParameter(AsmTypes.OBJECT_TYPE, false, null);
    }

    for (JvmMethodParameterSignature param : valueParameters) {
      if (param.getKind() == JvmMethodParameterKind.VALUE) {
        break;
      }
      invocationParamBuilder.addNextParameter(param.getAsmType(), false, null);
    }

    List<ParameterInfo> infos = invocationParamBuilder.listNotCaptured();
    putParameterOnStack(infos.toArray(new ParameterInfo[infos.size()]));
  }
コード例 #7
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();
    }
  }
コード例 #8
0
ファイル: FunctionCodegen.java プロジェクト: AlexJuca/kotlin
  private static void loadExplicitArgumentsOnStack(
      @NotNull Type ownerType,
      boolean isStatic,
      @NotNull JvmMethodSignature signature,
      @NotNull CallGenerator callGenerator) {
    int var = 0;
    if (!isStatic) {
      callGenerator.putValueIfNeeded(ownerType, StackValue.local(var, ownerType));
      var += ownerType.getSize();
    }

    for (JvmMethodParameterSignature parameterSignature : signature.getValueParameters()) {
      if (parameterSignature.getKind() != JvmMethodParameterKind.VALUE) {
        Type type = parameterSignature.getAsmType();
        callGenerator.putValueIfNeeded(type, StackValue.local(var, type));
        var += type.getSize();
      }
    }
  }
コード例 #9
0
ファイル: InlineCodegen.java プロジェクト: grigala/kotlin
  @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;
  }
コード例 #10
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());
  }
コード例 #11
0
ファイル: FunctionCodegen.java プロジェクト: AlexJuca/kotlin
  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);
      }
    }
  }
コード例 #12
0
ファイル: FunctionCodegen.java プロジェクト: AlexJuca/kotlin
  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());
  }