Search in sources :

Example 1 with Method

use of org.jetbrains.org.objectweb.asm.commons.Method in project kotlin by JetBrains.

the class ClosureCodegen method generateKotlinMetadataAnnotation.

@Override
protected void generateKotlinMetadataAnnotation() {
    FunctionDescriptor frontendFunDescriptor = CodegenUtilKt.unwrapFrontendVersion(funDescriptor);
    FunctionDescriptor freeLambdaDescriptor = createFreeLambdaDescriptor(frontendFunDescriptor);
    Method method = v.getSerializationBindings().get(METHOD_FOR_FUNCTION, frontendFunDescriptor);
    assert method != null : "No method for " + frontendFunDescriptor;
    v.getSerializationBindings().put(METHOD_FOR_FUNCTION, freeLambdaDescriptor, method);
    final DescriptorSerializer serializer = DescriptorSerializer.createForLambda(new JvmSerializerExtension(v.getSerializationBindings(), state));
    final ProtoBuf.Function functionProto = serializer.functionProto(freeLambdaDescriptor).build();
    WriteAnnotationUtilKt.writeKotlinMetadata(v, state, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0, new Function1<AnnotationVisitor, Unit>() {

        @Override
        public Unit invoke(AnnotationVisitor av) {
            writeAnnotationData(av, serializer, functionProto);
            return Unit.INSTANCE;
        }
    });
}
Also used : JvmSerializerExtension(org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension) DescriptorSerializer(org.jetbrains.kotlin.serialization.DescriptorSerializer) AnnotationVisitor(org.jetbrains.org.objectweb.asm.AnnotationVisitor) Method(org.jetbrains.org.objectweb.asm.commons.Method) Unit(kotlin.Unit) ProtoBuf(org.jetbrains.kotlin.serialization.ProtoBuf)

Example 2 with Method

use of org.jetbrains.org.objectweb.asm.commons.Method in project kotlin by JetBrains.

the class ClosureCodegen method generateConstructor.

@NotNull
protected Method generateConstructor() {
    List<FieldInfo> args = calculateConstructorParameters(typeMapper, closure, asmType);
    Type[] argTypes = fieldListToTypeArray(args);
    Method constructor = new Method("<init>", Type.VOID_TYPE, argTypes);
    MethodVisitor mv = v.newMethod(JvmDeclarationOriginKt.OtherOrigin(element, funDescriptor), visibilityFlag, "<init>", constructor.getDescriptor(), null, ArrayUtil.EMPTY_STRING_ARRAY);
    if (state.getClassBuilderMode().generateBodies) {
        mv.visitCode();
        InstructionAdapter iv = new InstructionAdapter(mv);
        Pair<Integer, Type> receiverIndexAndType = CallableReferenceUtilKt.generateClosureFieldsInitializationFromParameters(iv, closure, args);
        if (shouldHaveBoundReferenceReceiver && receiverIndexAndType == null) {
            throw new AssertionError("No bound reference receiver in constructor parameters: " + args);
        }
        int boundReferenceReceiverParameterIndex = shouldHaveBoundReferenceReceiver ? receiverIndexAndType.getFirst() : -1;
        Type boundReferenceReceiverType = shouldHaveBoundReferenceReceiver ? receiverIndexAndType.getSecond() : null;
        iv.load(0, superClassAsmType);
        String superClassConstructorDescriptor;
        if (superClassAsmType.equals(LAMBDA) || superClassAsmType.equals(FUNCTION_REFERENCE) || superClassAsmType.equals(CoroutineCodegenUtilKt.COROUTINE_IMPL_ASM_TYPE)) {
            int arity = calculateArity();
            iv.iconst(arity);
            if (shouldHaveBoundReferenceReceiver) {
                CallableReferenceUtilKt.loadBoundReferenceReceiverParameter(iv, boundReferenceReceiverParameterIndex, boundReferenceReceiverType);
                superClassConstructorDescriptor = "(ILjava/lang/Object;)V";
            } else {
                superClassConstructorDescriptor = "(I)V";
            }
        } else {
            assert !shouldHaveBoundReferenceReceiver : "Unexpected bound reference with supertype " + superClassAsmType;
            superClassConstructorDescriptor = "()V";
        }
        iv.invokespecial(superClassAsmType.getInternalName(), "<init>", superClassConstructorDescriptor, false);
        iv.visitInsn(RETURN);
        FunctionCodegen.endVisit(iv, "constructor", element);
    }
    return constructor;
}
Also used : KotlinType(org.jetbrains.kotlin.types.KotlinType) Type(org.jetbrains.org.objectweb.asm.Type) InstructionAdapter(org.jetbrains.org.objectweb.asm.commons.InstructionAdapter) Method(org.jetbrains.org.objectweb.asm.commons.Method) MethodVisitor(org.jetbrains.org.objectweb.asm.MethodVisitor) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with Method

use of org.jetbrains.org.objectweb.asm.commons.Method in project kotlin by JetBrains.

the class SignaturesPropagationData method getSuperFunctionsForMethod.

private static List<FunctionDescriptor> getSuperFunctionsForMethod(@NotNull JavaMethod method, @NotNull JavaMethodDescriptor autoMethodDescriptor, @NotNull ClassDescriptor containingClass) {
    List<FunctionDescriptor> superFunctions = Lists.newArrayList();
    // TODO: Add propagation for other kotlin descriptors (KT-3621)
    Name name = method.getName();
    Method autoSignature = null;
    boolean autoMethodContainsVararg = SignaturePropagationUtilKt.containsVarargs(autoMethodDescriptor);
    for (KotlinType supertype : containingClass.getTypeConstructor().getSupertypes()) {
        Collection<SimpleFunctionDescriptor> superFunctionCandidates = supertype.getMemberScope().getContributedFunctions(name, NoLookupLocation.WHEN_GET_SUPER_MEMBERS);
        if (!autoMethodContainsVararg && !SignaturePropagationUtilKt.containsAnyNotTrivialSignature(superFunctionCandidates))
            continue;
        if (autoSignature == null) {
            autoSignature = SIGNATURE_MAPPER.mapToJvmMethodSignature(autoMethodDescriptor);
        }
        for (FunctionDescriptor candidate : superFunctionCandidates) {
            // TODO: remove this continue when KT-15747 is fixed
            if (candidate.isSuspend())
                continue;
            Method candidateSignature = SIGNATURE_MAPPER.mapToJvmMethodSignature(candidate);
            if (KotlinToJvmSignatureMapperKt.erasedSignaturesEqualIgnoringReturnTypes(autoSignature, candidateSignature)) {
                superFunctions.add(candidate);
            }
        }
    }
    // sorting for diagnostic stability
    Collections.sort(superFunctions, new Comparator<FunctionDescriptor>() {

        @Override
        public int compare(@NotNull FunctionDescriptor fun1, @NotNull FunctionDescriptor fun2) {
            FqNameUnsafe fqName1 = getFqName(fun1.getContainingDeclaration());
            FqNameUnsafe fqName2 = getFqName(fun2.getContainingDeclaration());
            return fqName1.asString().compareTo(fqName2.asString());
        }
    });
    return superFunctions;
}
Also used : FqNameUnsafe(org.jetbrains.kotlin.name.FqNameUnsafe) KotlinType(org.jetbrains.kotlin.types.KotlinType) JavaMethod(org.jetbrains.kotlin.load.java.structure.JavaMethod) Method(org.jetbrains.org.objectweb.asm.commons.Method) DescriptorUtils.getFqName(org.jetbrains.kotlin.resolve.DescriptorUtils.getFqName) Name(org.jetbrains.kotlin.name.Name)

Example 4 with Method

use of org.jetbrains.org.objectweb.asm.commons.Method in project kotlin by JetBrains.

the class MethodInliner method doInline.

@NotNull
private MethodNode doInline(@NotNull MethodNode node) {
    final Deque<InvokeCall> currentInvokes = new LinkedList<InvokeCall>(invokeCalls);
    final MethodNode resultNode = new MethodNode(node.access, node.name, node.desc, node.signature, null);
    final Iterator<TransformationInfo> iterator = transformations.iterator();
    final TypeRemapper remapper = TypeRemapper.createFrom(currentTypeMapping);
    final RemappingMethodAdapter remappingMethodAdapter = new RemappingMethodAdapter(resultNode.access, resultNode.desc, resultNode, new AsmTypeRemapper(remapper, inliningContext.getRoot().typeParameterMappings == null, result));
    final int markerShift = InlineCodegenUtil.calcMarkerShift(parameters, node);
    InlineAdapter lambdaInliner = new InlineAdapter(remappingMethodAdapter, parameters.getArgsSizeOnStack(), sourceMapper) {

        private TransformationInfo transformationInfo;

        private void handleAnonymousObjectRegeneration() {
            transformationInfo = iterator.next();
            String oldClassName = transformationInfo.getOldClassName();
            if (transformationInfo.shouldRegenerate(isSameModule)) {
                //TODO: need poping of type but what to do with local funs???
                String newClassName = transformationInfo.getNewClassName();
                remapper.addMapping(oldClassName, newClassName);
                InliningContext childInliningContext = inliningContext.subInlineWithClassRegeneration(inliningContext.nameGenerator, currentTypeMapping, inlineCallSiteInfo);
                ObjectTransformer transformer = transformationInfo.createTransformer(childInliningContext, isSameModule);
                InlineResult transformResult = transformer.doTransform(nodeRemapper);
                result.merge(transformResult);
                result.addChangedType(oldClassName, newClassName);
                if (inliningContext.isInliningLambda && transformationInfo.canRemoveAfterTransformation()) {
                    // this class is transformed and original not used so we should remove original one after inlining
                    result.addClassToRemove(oldClassName);
                }
                if (transformResult.getReifiedTypeParametersUsages().wereUsedReifiedParameters()) {
                    ReifiedTypeInliner.putNeedClassReificationMarker(mv);
                    result.getReifiedTypeParametersUsages().mergeAll(transformResult.getReifiedTypeParametersUsages());
                }
            } else if (!transformationInfo.getWasAlreadyRegenerated()) {
                result.addNotChangedClass(oldClassName);
            }
        }

        @Override
        public void anew(@NotNull Type type) {
            if (isAnonymousClass(type.getInternalName())) {
                handleAnonymousObjectRegeneration();
            }
            //in case of regenerated transformationInfo type would be remapped to new one via remappingMethodAdapter
            super.anew(type);
        }

        @Override
        public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
            if (/*INLINE_RUNTIME.equals(owner) &&*/
            isInvokeOnLambda(owner, name)) {
                //TODO add method
                assert !currentInvokes.isEmpty();
                InvokeCall invokeCall = currentInvokes.remove();
                LambdaInfo info = invokeCall.lambdaInfo;
                if (info == null) {
                    //noninlinable lambda
                    super.visitMethodInsn(opcode, owner, name, desc, itf);
                    return;
                }
                //NB: don't inline cause it changes
                int valueParamShift = Math.max(getNextLocalIndex(), markerShift);
                putStackValuesIntoLocals(info.getInvokeParamsWithoutCaptured(), valueParamShift, this, desc);
                if (invokeCall.lambdaInfo.getFunctionDescriptor().getValueParameters().isEmpty()) {
                    // There won't be no parameters processing and line call can be left without actual instructions.
                    // Note: if function is called on the line with other instructions like 1 + foo(), 'nop' will still be generated.
                    visitInsn(Opcodes.NOP);
                }
                addInlineMarker(this, true);
                Parameters lambdaParameters = info.addAllParameters(nodeRemapper);
                InlinedLambdaRemapper newCapturedRemapper = new InlinedLambdaRemapper(info.getLambdaClassType().getInternalName(), nodeRemapper, lambdaParameters);
                setLambdaInlining(true);
                SMAP lambdaSMAP = info.getNode().getClassSMAP();
                //noinspection ConstantConditions
                SourceMapper mapper = inliningContext.classRegeneration && !inliningContext.isInliningLambda ? new NestedSourceMapper(sourceMapper, lambdaSMAP.getIntervals(), lambdaSMAP.getSourceInfo()) : new InlineLambdaSourceMapper(sourceMapper.getParent(), info.getNode());
                MethodInliner inliner = new MethodInliner(info.getNode().getNode(), lambdaParameters, inliningContext.subInlineLambda(info), newCapturedRemapper, true, /*cause all calls in same module as lambda*/
                "Lambda inlining " + info.getLambdaClassType().getInternalName(), mapper, inlineCallSiteInfo, null);
                LocalVarRemapper remapper = new LocalVarRemapper(lambdaParameters, valueParamShift);
                //TODO add skipped this and receiver
                InlineResult lambdaResult = inliner.doInline(this.mv, remapper, true, info, invokeCall.finallyDepthShift);
                result.mergeWithNotChangeInfo(lambdaResult);
                result.getReifiedTypeParametersUsages().mergeAll(lambdaResult.getReifiedTypeParametersUsages());
                //return value boxing/unboxing
                Method bridge = typeMapper.mapAsmMethod(ClosureCodegen.getErasedInvokeFunction(info.getFunctionDescriptor()));
                Method delegate = typeMapper.mapAsmMethod(info.getFunctionDescriptor());
                StackValue.onStack(delegate.getReturnType()).put(bridge.getReturnType(), this);
                setLambdaInlining(false);
                addInlineMarker(this, false);
                mapper.endMapping();
                if (inlineOnlySmapSkipper != null) {
                    inlineOnlySmapSkipper.markCallSiteLineNumber(remappingMethodAdapter);
                }
            } else if (isAnonymousConstructorCall(owner, name)) {
                //TODO add proper message
                assert transformationInfo instanceof AnonymousObjectTransformationInfo : "<init> call doesn't correspond to object transformation info: " + owner + "." + name + ", info " + transformationInfo;
                InliningContext parent = inliningContext.getParent();
                boolean shouldRegenerate = transformationInfo.shouldRegenerate(isSameModule);
                boolean isContinuation = parent != null && parent.isContinuation();
                if (shouldRegenerate || isContinuation) {
                    assert shouldRegenerate || inlineCallSiteInfo.getOwnerClassName().equals(transformationInfo.getOldClassName()) : "Only coroutines can call their own constructors";
                    //put additional captured parameters on stack
                    AnonymousObjectTransformationInfo info = (AnonymousObjectTransformationInfo) transformationInfo;
                    AnonymousObjectTransformationInfo oldInfo = inliningContext.findAnonymousObjectTransformationInfo(owner);
                    if (oldInfo != null && isContinuation) {
                        info = oldInfo;
                    }
                    for (CapturedParamDesc capturedParamDesc : info.getAllRecapturedParameters()) {
                        visitFieldInsn(Opcodes.GETSTATIC, capturedParamDesc.getContainingLambdaName(), "$$$" + capturedParamDesc.getFieldName(), capturedParamDesc.getType().getDescriptor());
                    }
                    super.visitMethodInsn(opcode, info.getNewClassName(), name, info.getNewConstructorDescriptor(), itf);
                    //TODO: add new inner class also for other contexts
                    if (inliningContext.getParent() instanceof RegeneratedClassContext) {
                        inliningContext.getParent().typeRemapper.addAdditionalMappings(transformationInfo.getOldClassName(), transformationInfo.getNewClassName());
                    }
                    transformationInfo = null;
                } else {
                    super.visitMethodInsn(opcode, owner, name, desc, itf);
                }
            } else if (!inliningContext.isInliningLambda && ReifiedTypeInliner.isNeedClassReificationMarker(new MethodInsnNode(opcode, owner, name, desc, false))) {
            //we shouldn't process here content of inlining lambda it should be reified at external level
            } else {
                super.visitMethodInsn(opcode, owner, name, desc, itf);
            }
        }

        @Override
        public void visitFieldInsn(int opcode, @NotNull String owner, @NotNull String name, @NotNull String desc) {
            if (opcode == Opcodes.GETSTATIC && (isAnonymousSingletonLoad(owner, name) || isWhenMappingAccess(owner, name))) {
                handleAnonymousObjectRegeneration();
            }
            super.visitFieldInsn(opcode, owner, name, desc);
        }

        @Override
        public void visitMaxs(int stack, int locals) {
            lambdasFinallyBlocks = resultNode.tryCatchBlocks.size();
            super.visitMaxs(stack, locals);
        }
    };
    node.accept(lambdaInliner);
    return resultNode;
}
Also used : RemappingMethodAdapter(org.jetbrains.org.objectweb.asm.commons.RemappingMethodAdapter) NotNull(org.jetbrains.annotations.NotNull) Method(org.jetbrains.org.objectweb.asm.commons.Method) Type(org.jetbrains.org.objectweb.asm.Type) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with Method

use of org.jetbrains.org.objectweb.asm.commons.Method in project kotlin by JetBrains.

the class KotlinTypeMapper method mapDefaultMethod.

@NotNull
public Method mapDefaultMethod(@NotNull FunctionDescriptor functionDescriptor, @NotNull OwnerKind kind) {
    Method jvmSignature = mapAsmMethod(functionDescriptor, kind);
    Type ownerType = mapOwner(functionDescriptor);
    boolean isConstructor = isConstructor(jvmSignature);
    String descriptor = getDefaultDescriptor(jvmSignature, isStaticMethod(kind, functionDescriptor) || isConstructor ? null : ownerType.getDescriptor(), CodegenUtilKt.unwrapFrontendVersion(functionDescriptor));
    return new Method(isConstructor ? "<init>" : jvmSignature.getName() + JvmAbi.DEFAULT_PARAMS_IMPL_SUFFIX, descriptor);
}
Also used : Type(org.jetbrains.org.objectweb.asm.Type) AsmUtil.isStaticMethod(org.jetbrains.kotlin.codegen.AsmUtil.isStaticMethod) Method(org.jetbrains.org.objectweb.asm.commons.Method) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

Method (org.jetbrains.org.objectweb.asm.commons.Method)25 KotlinType (org.jetbrains.kotlin.types.KotlinType)11 Type (org.jetbrains.org.objectweb.asm.Type)9 NotNull (org.jetbrains.annotations.NotNull)7 InstructionAdapter (org.jetbrains.org.objectweb.asm.commons.InstructionAdapter)5 Unit (kotlin.Unit)3 JvmMethodGenericSignature (org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodGenericSignature)2 JvmMethodSignature (org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature)2 MethodVisitor (org.jetbrains.org.objectweb.asm.MethodVisitor)2 MethodNode (org.jetbrains.org.objectweb.asm.tree.MethodNode)2 TraceMethodVisitor (org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor)2 InstrumentationClassFinder (com.intellij.compiler.instrumentation.InstrumentationClassFinder)1 PsiElement (com.intellij.psi.PsiElement)1 IElementType (com.intellij.psi.tree.IElementType)1 SupportCode (com.intellij.uiDesigner.core.SupportCode)1 FontDescriptor (com.intellij.uiDesigner.lw.FontDescriptor)1 LwComponent (com.intellij.uiDesigner.lw.LwComponent)1 StringDescriptor (com.intellij.uiDesigner.lw.StringDescriptor)1 ArrayList (java.util.ArrayList)1 Bridge (org.jetbrains.kotlin.backend.common.bridges.Bridge)1