Search in sources :

Example 6 with InstructionAdapter

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

the class MemberCodegen method generatePropertyMetadataArrayFieldIfNeeded.

protected void generatePropertyMetadataArrayFieldIfNeeded(@NotNull Type thisAsmType) {
    List<KtProperty> delegatedProperties = new ArrayList<KtProperty>();
    for (KtDeclaration declaration : ((KtDeclarationContainer) element).getDeclarations()) {
        if (declaration instanceof KtProperty) {
            KtProperty property = (KtProperty) declaration;
            if (property.hasDelegate()) {
                delegatedProperties.add(property);
            }
        }
    }
    if (delegatedProperties.isEmpty())
        return;
    v.newField(NO_ORIGIN, ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, "[" + K_PROPERTY_TYPE, null, null);
    if (!state.getClassBuilderMode().generateBodies)
        return;
    InstructionAdapter iv = createOrGetClInitCodegen().v;
    iv.iconst(delegatedProperties.size());
    iv.newarray(K_PROPERTY_TYPE);
    for (int i = 0, size = delegatedProperties.size(); i < size; i++) {
        PropertyDescriptor property = (PropertyDescriptor) BindingContextUtils.getNotNull(bindingContext, VARIABLE, delegatedProperties.get(i));
        iv.dup();
        iv.iconst(i);
        int receiverCount = (property.getDispatchReceiverParameter() != null ? 1 : 0) + (property.getExtensionReceiverParameter() != null ? 1 : 0);
        Type implType = property.isVar() ? MUTABLE_PROPERTY_REFERENCE_IMPL[receiverCount] : PROPERTY_REFERENCE_IMPL[receiverCount];
        iv.anew(implType);
        iv.dup();
        // TODO: generate the container once and save to a local field instead (KT-10495)
        ClosureCodegen.generateCallableReferenceDeclarationContainer(iv, property, state);
        iv.aconst(property.getName().asString());
        PropertyReferenceCodegen.generateCallableReferenceSignature(iv, property, state);
        iv.invokespecial(implType.getInternalName(), "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, K_DECLARATION_CONTAINER_TYPE, JAVA_STRING_TYPE, JAVA_STRING_TYPE), false);
        Method wrapper = PropertyReferenceCodegen.getWrapperMethodForPropertyReference(property, receiverCount);
        iv.invokestatic(REFLECTION, wrapper.getName(), wrapper.getDescriptor(), false);
        StackValue.onStack(implType).put(K_PROPERTY_TYPE, iv);
        iv.astore(K_PROPERTY_TYPE);
    }
    iv.putstatic(thisAsmType.getInternalName(), JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME, "[" + K_PROPERTY_TYPE);
}
Also used : KotlinType(org.jetbrains.kotlin.types.KotlinType) InstructionAdapter(org.jetbrains.org.objectweb.asm.commons.InstructionAdapter) Method(org.jetbrains.org.objectweb.asm.commons.Method)

Example 7 with InstructionAdapter

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

the class FunctionCodegen method generateDelegateForDefaultImpl.

private void generateDelegateForDefaultImpl(@NotNull final FunctionDescriptor functionDescriptor, @Nullable PsiElement element) {
    Method defaultImplMethod = typeMapper.mapAsmMethod(functionDescriptor, OwnerKind.DEFAULT_IMPLS);
    CodegenUtilKt.generateMethod(v, "Default Impl delegate in interface", Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC | Opcodes.ACC_PUBLIC, new Method(defaultImplMethod.getName() + JvmAbi.DEFAULT_IMPLS_DELEGATE_SUFFIX, defaultImplMethod.getDescriptor()), element, JvmDeclarationOrigin.NO_ORIGIN, state, new Function1<InstructionAdapter, Unit>() {

        @Override
        public Unit invoke(InstructionAdapter adapter) {
            Method interfaceMethod = typeMapper.mapAsmMethod(functionDescriptor, OwnerKind.IMPLEMENTATION);
            Type type = typeMapper.mapOwner(functionDescriptor);
            generateDelegateToMethodBody(-1, adapter, interfaceMethod, type.getInternalName(), Opcodes.INVOKESPECIAL, true);
            return null;
        }
    });
}
Also used : KotlinType(org.jetbrains.kotlin.types.KotlinType) InstructionAdapter(org.jetbrains.org.objectweb.asm.commons.InstructionAdapter) Method(org.jetbrains.org.objectweb.asm.commons.Method) Unit(kotlin.Unit)

Example 8 with InstructionAdapter

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

the class FunctionCodegen method generateDefaultImplBody.

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().mapSignatureWithGeneric(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, functionDescriptor, defaultMethod);
    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);
        }
    }
    // load arguments after defaults generation to avoid redundant stack normalization operations
    loadExplicitArgumentsOnStack(OBJECT_TYPE, isStatic, signature, generator);
    for (int index = 0; index < valueParameters.size(); index++) {
        ValueParameterDescriptor parameterDescriptor = valueParameters.get(index);
        Type type = mappedParameters.get(capturedArgumentsCount + index).getAsmType();
        int parameterIndex = frameMap.getIndex(parameterDescriptor);
        generator.putValueIfNeeded(type, StackValue.local(parameterIndex, type));
    }
    CallableMethod method = state.getTypeMapper().mapToCallableMethod(functionDescriptor, false);
    generator.genCall(method, null, false, codegen);
    iv.areturn(signature.getReturnType());
}
Also used : JvmMethodParameterSignature(org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature) GenerationState(org.jetbrains.kotlin.codegen.state.GenerationState) JvmMethodSignature(org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature) KotlinType(org.jetbrains.kotlin.types.KotlinType) InstructionAdapter(org.jetbrains.org.objectweb.asm.commons.InstructionAdapter)

Example 9 with InstructionAdapter

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

the class ExpressionCodegen method visitPostfixExpression.

@Override
public StackValue visitPostfixExpression(@NotNull final KtPostfixExpression expression, StackValue receiver) {
    if (expression.getOperationReference().getReferencedNameElementType() == KtTokens.EXCLEXCL) {
        final StackValue base = genQualified(receiver, expression.getBaseExpression());
        if (isPrimitive(base.type)) {
            return base;
        } else {
            return StackValue.operation(base.type, new Function1<InstructionAdapter, Unit>() {

                @Override
                public Unit invoke(InstructionAdapter v) {
                    base.put(base.type, v);
                    v.dup();
                    Label ok = new Label();
                    v.ifnonnull(ok);
                    v.invokestatic(IntrinsicMethods.INTRINSICS_CLASS_NAME, "throwNpe", "()V", false);
                    v.mark(ok);
                    return null;
                }
            });
        }
    }
    DeclarationDescriptor originalOperation = bindingContext.get(REFERENCE_TARGET, expression.getOperationReference());
    String originalOperationName = originalOperation != null ? originalOperation.getName().asString() : null;
    final ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(expression, bindingContext);
    DeclarationDescriptor op = resolvedCall.getResultingDescriptor();
    if (!(op instanceof FunctionDescriptor) || originalOperation == null) {
        throw new UnsupportedOperationException("Don't know how to generate this postfix expression: " + originalOperationName + " " + op);
    }
    final Type asmResultType = expressionType(expression);
    final Type asmBaseType = expressionType(expression.getBaseExpression());
    DeclarationDescriptor cls = op.getContainingDeclaration();
    final int increment;
    if (originalOperationName.equals("inc")) {
        increment = 1;
    } else if (originalOperationName.equals("dec")) {
        increment = -1;
    } else {
        throw new UnsupportedOperationException("Unsupported postfix operation: " + originalOperationName + " " + op);
    }
    final boolean isPrimitiveNumberClassDescriptor = isPrimitiveNumberClassDescriptor(cls);
    if (isPrimitiveNumberClassDescriptor && AsmUtil.isPrimitive(asmBaseType)) {
        KtExpression operand = expression.getBaseExpression();
        // Optimization for j = i++, when j and i are Int without any smart cast: we just work with primitive int
        if (operand instanceof KtReferenceExpression && asmResultType == Type.INT_TYPE && bindingContext.get(BindingContext.SMARTCAST, operand) == null) {
            int index = indexOfLocalNotDelegated((KtReferenceExpression) operand);
            if (index >= 0) {
                return StackValue.postIncrement(index, increment);
            }
        }
    }
    return StackValue.operation(asmBaseType, new Function1<InstructionAdapter, Unit>() {

        @Override
        public Unit invoke(InstructionAdapter v) {
            StackValue value = StackValue.complexWriteReadReceiver(gen(expression.getBaseExpression()));
            value.put(asmBaseType, v);
            AsmUtil.dup(v, asmBaseType);
            StackValue previousValue = StackValue.local(myFrameMap.enterTemp(asmBaseType), asmBaseType);
            previousValue.store(StackValue.onStack(asmBaseType), v);
            Type storeType;
            if (isPrimitiveNumberClassDescriptor && AsmUtil.isPrimitive(asmBaseType)) {
                genIncrement(asmBaseType, increment, v);
                storeType = asmBaseType;
            } else {
                StackValue result = invokeFunction(resolvedCall, StackValue.onStack(asmBaseType));
                result.put(result.type, v);
                storeType = result.type;
            }
            value.store(StackValue.onStack(storeType), v, true);
            previousValue.put(asmBaseType, v);
            myFrameMap.leaveTemp(asmBaseType);
            return Unit.INSTANCE;
        }
    });
}
Also used : Label(org.jetbrains.org.objectweb.asm.Label) Unit(kotlin.Unit) IElementType(com.intellij.psi.tree.IElementType) Type(org.jetbrains.org.objectweb.asm.Type) KotlinType(org.jetbrains.kotlin.types.KotlinType) InstructionAdapter(org.jetbrains.org.objectweb.asm.commons.InstructionAdapter)

Example 10 with InstructionAdapter

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

the class ExpressionCodegen method generateIfExpression.

/* package */
StackValue generateIfExpression(@NotNull final KtIfExpression expression, final boolean isStatement) {
    final Type asmType = isStatement ? Type.VOID_TYPE : expressionTypeForBranchingOperation(expression);
    final StackValue condition = gen(expression.getCondition());
    final KtExpression thenExpression = expression.getThen();
    final KtExpression elseExpression = expression.getElse();
    if (isEmptyExpression(thenExpression)) {
        if (isEmptyExpression(elseExpression)) {
            return StackValue.coercion(condition, asmType);
        }
        return generateSingleBranchIf(condition, expression, elseExpression, false, isStatement);
    } else {
        if (isEmptyExpression(elseExpression)) {
            return generateSingleBranchIf(condition, expression, thenExpression, true, isStatement);
        }
    }
    return StackValue.operation(asmType, new Function1<InstructionAdapter, Unit>() {

        @Override
        public Unit invoke(InstructionAdapter v) {
            Label elseLabel = new Label();
            BranchedValue.Companion.condJump(condition, elseLabel, true, v);
            Label end = new Label();
            gen(thenExpression, asmType);
            v.goTo(end);
            v.mark(elseLabel);
            gen(elseExpression, asmType);
            markLineNumber(expression, isStatement);
            v.mark(end);
            return Unit.INSTANCE;
        }
    });
}
Also used : IElementType(com.intellij.psi.tree.IElementType) Type(org.jetbrains.org.objectweb.asm.Type) KotlinType(org.jetbrains.kotlin.types.KotlinType) InstructionAdapter(org.jetbrains.org.objectweb.asm.commons.InstructionAdapter) Label(org.jetbrains.org.objectweb.asm.Label) Unit(kotlin.Unit)

Aggregations

InstructionAdapter (org.jetbrains.org.objectweb.asm.commons.InstructionAdapter)35 KotlinType (org.jetbrains.kotlin.types.KotlinType)23 Type (org.jetbrains.org.objectweb.asm.Type)16 IElementType (com.intellij.psi.tree.IElementType)10 Unit (kotlin.Unit)10 MethodVisitor (org.jetbrains.org.objectweb.asm.MethodVisitor)7 Label (org.jetbrains.org.objectweb.asm.Label)5 Method (org.jetbrains.org.objectweb.asm.commons.Method)5 JavaClassDescriptor (org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor)4 NotNull (org.jetbrains.annotations.NotNull)3 Type.getObjectType (org.jetbrains.org.objectweb.asm.Type.getObjectType)3 Nullable (org.jetbrains.annotations.Nullable)2 PrimitiveType (org.jetbrains.kotlin.builtins.PrimitiveType)2 JvmPrimitiveType (org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType)2 JvmMethodSignature (org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature)2 TypeUtils.isNullableType (org.jetbrains.kotlin.types.TypeUtils.isNullableType)2 TraceMethodVisitor (org.jetbrains.org.objectweb.asm.util.TraceMethodVisitor)2 Method (java.lang.reflect.Method)1 KotlinBuiltIns (org.jetbrains.kotlin.builtins.KotlinBuiltIns)1 AsmUtil.getVisibilityForBackingField (org.jetbrains.kotlin.codegen.AsmUtil.getVisibilityForBackingField)1