Search in sources :

Example 66 with Type

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

the class KotlinTypeMapper method writeAdditionalConstructorParameters.

private void writeAdditionalConstructorParameters(@NotNull ClassConstructorDescriptor descriptor, @NotNull JvmSignatureWriter sw) {
    boolean isSynthesized = descriptor.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED;
    //if (isSynthesized) return;
    MutableClosure closure = bindingContext.get(CodegenBinding.CLOSURE, descriptor.getContainingDeclaration());
    ClassDescriptor captureThis = getDispatchReceiverParameterForConstructorCall(descriptor, closure);
    if (!isSynthesized && captureThis != null) {
        writeParameter(sw, JvmMethodParameterKind.OUTER, captureThis.getDefaultType(), descriptor);
    }
    KotlinType captureReceiverType = closure != null ? closure.getCaptureReceiverType() : null;
    if (captureReceiverType != null) {
        writeParameter(sw, JvmMethodParameterKind.RECEIVER, captureReceiverType, descriptor);
    }
    ClassDescriptor containingDeclaration = descriptor.getContainingDeclaration();
    if (!isSynthesized) {
        if (containingDeclaration.getKind() == ClassKind.ENUM_CLASS || containingDeclaration.getKind() == ClassKind.ENUM_ENTRY) {
            writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getStringType(), descriptor);
            writeParameter(sw, JvmMethodParameterKind.ENUM_NAME_OR_ORDINAL, DescriptorUtilsKt.getBuiltIns(descriptor).getIntType(), descriptor);
        }
    }
    if (closure == null)
        return;
    for (DeclarationDescriptor variableDescriptor : closure.getCaptureVariables().keySet()) {
        Type type;
        if (variableDescriptor instanceof VariableDescriptor && !(variableDescriptor instanceof PropertyDescriptor)) {
            Type sharedVarType = getSharedVarType(variableDescriptor);
            if (sharedVarType == null) {
                if (isDelegatedLocalVariable(variableDescriptor)) {
                    VariableDescriptor delegateVariableDescriptor = bindingContext.get(LOCAL_VARIABLE_DELEGATE, (VariableDescriptor) variableDescriptor);
                    assert delegateVariableDescriptor != null : "Local delegated property " + variableDescriptor + " delegate descriptor should be not null";
                    sharedVarType = mapType(delegateVariableDescriptor.getType());
                } else {
                    sharedVarType = mapType(((VariableDescriptor) variableDescriptor).getType());
                }
            }
            type = sharedVarType;
        } else if (isLocalFunction(variableDescriptor)) {
            //noinspection CastConflictsWithInstanceof
            type = asmTypeForAnonymousClass(bindingContext, (FunctionDescriptor) variableDescriptor);
        } else {
            type = null;
        }
        if (type != null) {
            closure.setCapturedParameterOffsetInConstructor(variableDescriptor, sw.getCurrentSignatureSize() + 1);
            writeParameter(sw, JvmMethodParameterKind.CAPTURED_LOCAL_VARIABLE, type);
        }
    }
    // because such classes are not accessible from the outside world
    if (classBuilderMode.generateBodies) {
        ResolvedCall<ConstructorDescriptor> superCall = findFirstDelegatingSuperCall(descriptor);
        if (superCall == null)
            return;
        writeSuperConstructorCallParameters(sw, descriptor, superCall, captureThis != null);
    }
}
Also used : Type(org.jetbrains.org.objectweb.asm.Type) DeserializedClassDescriptor(org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor) FunctionClassDescriptor(org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor) JavaClassDescriptor(org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor) MutableClosure(org.jetbrains.kotlin.codegen.binding.MutableClosure) TypeAliasConstructorDescriptor(org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor) LocalVariableDescriptor(org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor)

Example 67 with Type

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

the class EnumSwitchCodegen method generateSubject.

@Override
protected void generateSubject() {
    codegen.getState().getMappingsClassesForWhenByEnum().generateMappingsClassForExpression(expression);
    super.generateSubject();
    generateNullCheckIfNeeded();
    v.getstatic(mapping.getMappingsClassInternalName(), mapping.getFieldName(), MappingClassesForWhenByEnumCodegen.MAPPINGS_FIELD_DESCRIPTOR);
    v.swap();
    Type enumType = codegen.getState().getTypeMapper().mapClass(mapping.getEnumClassDescriptor());
    v.invokevirtual(enumType.getInternalName(), "ordinal", Type.getMethodDescriptor(Type.INT_TYPE), false);
    v.aload(Type.INT_TYPE);
}
Also used : Type(org.jetbrains.org.objectweb.asm.Type)

Example 68 with Type

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

the class InlineCodegen method recordParameterValueInLocalVal.

private Runnable recordParameterValueInLocalVal(boolean delayedWritingToLocals, @NotNull final ParameterInfo... infos) {
    final int[] index = new int[infos.length];
    for (int i = 0; i < infos.length; i++) {
        ParameterInfo info = infos[i];
        if (!info.isSkippedOrRemapped()) {
            index[i] = codegen.getFrameMap().enterTemp(info.getType());
        } else {
            index[i] = -1;
        }
    }
    Runnable runnable = new Runnable() {

        @Override
        public void run() {
            for (int i = infos.length - 1; i >= 0; i--) {
                ParameterInfo info = infos[i];
                if (!info.isSkippedOrRemapped()) {
                    Type type = info.type;
                    StackValue.Local local = StackValue.local(index[i], type);
                    local.store(StackValue.onStack(type), codegen.v);
                    if (info instanceof CapturedParamInfo) {
                        info.setRemapValue(local);
                        ((CapturedParamInfo) info).setSynthetic(true);
                    }
                }
            }
        }
    };
    if (delayedWritingToLocals)
        return runnable;
    runnable.run();
    return null;
}
Also used : Type(org.jetbrains.org.objectweb.asm.Type) KotlinType(org.jetbrains.kotlin.types.KotlinType)

Example 69 with Type

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

the class InternalFinallyBlockInliner method processInlineFunFinallyBlocks.

private void processInlineFunFinallyBlocks() {
    int nextTempNonLocalVarIndex = initAndGetVarIndexForNonLocalReturnValue();
    InsnList instructions = inlineFun.instructions;
    //As we do finally block code search after non-local return instruction
    // we should be sure that all others non-local returns already processed in this finally block.
    // So we do instruction processing in reverse order!
    AbstractInsnNode curIns = instructions.getLast();
    while (curIns != null) {
        processInstruction(curIns, false);
        //At this point only global return is possible, local one already substituted with: goto endLabel
        if (!InlineCodegenUtil.isReturnOpcode(curIns.getOpcode()) || !InlineCodegenUtil.isMarkedReturn(curIns)) {
            curIns = curIns.getPrevious();
            continue;
        }
        List<TryCatchBlockNodeInfo> currentCoveringNodesFromInnermost = sortTryCatchBlocks(new ArrayList<TryCatchBlockNodeInfo>(getTryBlocksMetaInfo().getCurrentIntervals()));
        checkCoveringBlocksInvariant(Lists.reverse(currentCoveringNodesFromInnermost));
        if (currentCoveringNodesFromInnermost.isEmpty() || currentCoveringNodesFromInnermost.get(currentCoveringNodesFromInnermost.size() - 1).getOnlyCopyNotProcess()) {
            curIns = curIns.getPrevious();
            continue;
        }
        AbstractInsnNode markedReturn = curIns;
        AbstractInsnNode instrInsertFinallyBefore = markedReturn.getPrevious();
        AbstractInsnNode nextPrev = instrInsertFinallyBefore.getPrevious();
        assert markedReturn.getNext() instanceof LabelNode : "Label should be occurred after non-local return";
        LabelNode newFinallyEnd = (LabelNode) markedReturn.getNext();
        Type nonLocalReturnType = InlineCodegenUtil.getReturnType(markedReturn.getOpcode());
        //Generally there could be several tryCatch blocks (group) on one code interval (same start and end labels, but maybe different handlers) -
        // all of them refer to one try/*catches*/finally or try/catches.
        // Each group that corresponds to try/*catches*/finally contains tryCatch block with default handler.
        // For each such group we should insert corresponding finally before non-local return.
        // So we split all try blocks on current instructions to groups and process them independently
        List<TryBlockCluster<TryCatchBlockNodeInfo>> clustersFromInnermost = TryBlockClusteringKt.doClustering(currentCoveringNodesFromInnermost);
        Iterator<TryBlockCluster<TryCatchBlockNodeInfo>> tryCatchBlockIterator = clustersFromInnermost.iterator();
        checkClusterInvariant(clustersFromInnermost);
        int originalDepthIndex = 0;
        while (tryCatchBlockIterator.hasNext()) {
            TryBlockCluster<TryCatchBlockNodeInfo> clusterToFindFinally = tryCatchBlockIterator.next();
            List<TryCatchBlockNodeInfo> clusterBlocks = clusterToFindFinally.getBlocks();
            TryCatchBlockNodeInfo nodeWithDefaultHandlerIfExists = clusterBlocks.get(clusterBlocks.size() - 1);
            FinallyBlockInfo finallyInfo = findFinallyBlockBody(nodeWithDefaultHandlerIfExists, getTryBlocksMetaInfo().getAllIntervals());
            if (finallyInfo == null)
                continue;
            if (nodeWithDefaultHandlerIfExists.getOnlyCopyNotProcess()) {
                //so it's a gap in try/catch handlers
                throw new RuntimeException("Lambda try blocks should be skipped");
            }
            originalDepthIndex++;
            instructions.resetLabels();
            List<TryCatchBlockNodePosition> tryCatchBlockInlinedInFinally = findTryCatchBlocksInlinedInFinally(finallyInfo);
            //Creating temp node for finally block copy with some additional instruction
            MethodNode finallyBlockCopy = createEmptyMethodNode();
            Label newFinallyStart = new Label();
            Label insertedBlockEnd = new Label();
            boolean generateAloadAstore = nonLocalReturnType != Type.VOID_TYPE && !finallyInfo.isEmpty();
            if (generateAloadAstore) {
                finallyBlockCopy.visitVarInsn(nonLocalReturnType.getOpcode(Opcodes.ISTORE), nextTempNonLocalVarIndex);
            }
            finallyBlockCopy.visitLabel(newFinallyStart);
            //Keep some information about label nodes, we need it to understand whether it's jump inside finally block or outside
            // in first case we do call VISIT on instruction otherwise recreating jump instruction (see below)
            Set<LabelNode> labelsInsideFinally = rememberOriginalLabelNodes(finallyInfo);
            //Writing finally block body to temporary node
            AbstractInsnNode currentIns = finallyInfo.startIns;
            while (currentIns != finallyInfo.endInsExclusive) {
                boolean isInsOrJumpInsideFinally = !(currentIns instanceof JumpInsnNode) || labelsInsideFinally.contains(((JumpInsnNode) currentIns).label);
                copyInstruction(finallyBlockCopy, currentIns, isInsOrJumpInsideFinally, originalDepthIndex);
                currentIns = currentIns.getNext();
            }
            if (generateAloadAstore) {
                finallyBlockCopy.visitVarInsn(nonLocalReturnType.getOpcode(Opcodes.ILOAD), nextTempNonLocalVarIndex);
                //TODO: do more wise indexing
                nextTempNonLocalVarIndex += nonLocalReturnType.getSize();
            }
            finallyBlockCopy.visitLabel(insertedBlockEnd);
            //Copying finally body before non-local return instruction
            InlineCodegenUtil.insertNodeBefore(finallyBlockCopy, inlineFun, instrInsertFinallyBefore);
            updateExceptionTable(clusterBlocks, newFinallyStart, newFinallyEnd, tryCatchBlockInlinedInFinally, labelsInsideFinally, (LabelNode) insertedBlockEnd.info);
        }
        //skip just inserted finally
        curIns = markedReturn.getPrevious();
        while (curIns != null && curIns != nextPrev) {
            processInstruction(curIns, false);
            curIns = curIns.getPrevious();
        }
        //finally block inserted so we need split update localVarTable in lambda
        if (instrInsertFinallyBefore.getPrevious() != nextPrev && curIns != null) {
            LabelNode startNode = new LabelNode();
            LabelNode endNode = new LabelNode();
            instructions.insert(curIns, startNode);
            //TODO: note that on return expression we have no variables
            instructions.insert(markedReturn, endNode);
            getLocalVarsMetaInfo().splitCurrentIntervals(new SimpleInterval(startNode, endNode), true);
        }
    }
    substituteTryBlockNodes(inlineFun);
    substituteLocalVarTable(inlineFun);
}
Also used : Label(org.jetbrains.org.objectweb.asm.Label) Type(org.jetbrains.org.objectweb.asm.Type)

Example 70 with Type

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

the class LambdaInfo method getCapturedVars.

@NotNull
public List<CapturedParamDesc> getCapturedVars() {
    //lazy initialization cause it would be calculated after object creation
    if (capturedVars == null) {
        capturedVars = new ArrayList<CapturedParamDesc>();
        if (closure.getCaptureThis() != null) {
            Type type = typeMapper.mapType(closure.getCaptureThis());
            EnclosedValueDescriptor descriptor = new EnclosedValueDescriptor(AsmUtil.CAPTURED_THIS_FIELD, /* descriptor = */
            null, StackValue.field(type, closureClassType, AsmUtil.CAPTURED_THIS_FIELD, false, StackValue.LOCAL_0), type);
            capturedVars.add(getCapturedParamInfo(descriptor));
        }
        if (closure.getCaptureReceiverType() != null) {
            Type type = typeMapper.mapType(closure.getCaptureReceiverType());
            EnclosedValueDescriptor descriptor = new EnclosedValueDescriptor(AsmUtil.CAPTURED_RECEIVER_FIELD, /* descriptor = */
            null, StackValue.field(type, closureClassType, AsmUtil.CAPTURED_RECEIVER_FIELD, false, StackValue.LOCAL_0), type);
            capturedVars.add(getCapturedParamInfo(descriptor));
        }
        for (EnclosedValueDescriptor descriptor : closure.getCaptureVariables().values()) {
            capturedVars.add(getCapturedParamInfo(descriptor));
        }
    }
    return capturedVars;
}
Also used : Type(org.jetbrains.org.objectweb.asm.Type) EnclosedValueDescriptor(org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

Type (org.jetbrains.org.objectweb.asm.Type)104 KotlinType (org.jetbrains.kotlin.types.KotlinType)66 IElementType (com.intellij.psi.tree.IElementType)45 NotNull (org.jetbrains.annotations.NotNull)23 InstructionAdapter (org.jetbrains.org.objectweb.asm.commons.InstructionAdapter)16 Label (org.jetbrains.org.objectweb.asm.Label)12 Type.getObjectType (org.jetbrains.org.objectweb.asm.Type.getObjectType)10 Method (org.jetbrains.org.objectweb.asm.commons.Method)9 Unit (kotlin.Unit)8 LocalVariableDescriptor (org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor)7 ArrayList (java.util.ArrayList)5 JavaClassDescriptor (org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor)5 MethodVisitor (org.jetbrains.org.objectweb.asm.MethodVisitor)5 PrimitiveType (org.jetbrains.kotlin.builtins.PrimitiveType)4 ValueParameterDescriptor (org.jetbrains.kotlin.descriptors.ValueParameterDescriptor)4 List (java.util.List)3 Nullable (org.jetbrains.annotations.Nullable)3 ScriptDescriptor (org.jetbrains.kotlin.descriptors.ScriptDescriptor)3 InOut (com.intellij.codeInspection.bytecodeAnalysis.Direction.InOut)2 FunctionClassDescriptor (org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor)2