Search in sources :

Example 31 with InstructionAdapter

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

the class ImplementationBodyCodegen method generateToArray.

private void generateToArray() {
    if (descriptor.getKind() == ClassKind.INTERFACE)
        return;
    final KotlinBuiltIns builtIns = DescriptorUtilsKt.getBuiltIns(descriptor);
    if (!isSubclass(descriptor, builtIns.getCollection()))
        return;
    if (CollectionsKt.any(DescriptorUtilsKt.getAllSuperclassesWithoutAny(descriptor), new Function1<ClassDescriptor, Boolean>() {

        @Override
        public Boolean invoke(ClassDescriptor classDescriptor) {
            return !(classDescriptor instanceof JavaClassDescriptor) && isSubclass(classDescriptor, builtIns.getCollection());
        }
    }))
        return;
    Collection<SimpleFunctionDescriptor> functions = descriptor.getDefaultType().getMemberScope().getContributedFunctions(Name.identifier("toArray"), NoLookupLocation.FROM_BACKEND);
    boolean hasGenericToArray = false;
    boolean hasNonGenericToArray = false;
    for (FunctionDescriptor function : functions) {
        hasGenericToArray |= isGenericToArray(function);
        hasNonGenericToArray |= isNonGenericToArray(function);
    }
    if (!hasNonGenericToArray) {
        MethodVisitor mv = v.newMethod(NO_ORIGIN, ACC_PUBLIC, "toArray", "()[Ljava/lang/Object;", null, null);
        InstructionAdapter iv = new InstructionAdapter(mv);
        mv.visitCode();
        iv.load(0, classAsmType);
        iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;)[Ljava/lang/Object;", false);
        iv.areturn(Type.getType("[Ljava/lang/Object;"));
        FunctionCodegen.endVisit(mv, "toArray", myClass);
    }
    if (!hasGenericToArray) {
        MethodVisitor mv = v.newMethod(NO_ORIGIN, ACC_PUBLIC, "toArray", "([Ljava/lang/Object;)[Ljava/lang/Object;", "<T:Ljava/lang/Object;>([TT;)[TT;", null);
        InstructionAdapter iv = new InstructionAdapter(mv);
        mv.visitCode();
        iv.load(0, classAsmType);
        iv.load(1, Type.getType("[Ljava/lang/Object;"));
        iv.invokestatic("kotlin/jvm/internal/CollectionToArray", "toArray", "(Ljava/util/Collection;[Ljava/lang/Object;)[Ljava/lang/Object;", false);
        iv.areturn(Type.getType("[Ljava/lang/Object;"));
        FunctionCodegen.endVisit(mv, "toArray", myClass);
    }
}
Also used : JavaClassDescriptor(org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor) InstructionAdapter(org.jetbrains.org.objectweb.asm.commons.InstructionAdapter) KotlinBuiltIns(org.jetbrains.kotlin.builtins.KotlinBuiltIns) JavaClassDescriptor(org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor) MethodVisitor(org.jetbrains.org.objectweb.asm.MethodVisitor)

Example 32 with InstructionAdapter

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

the class ImplementationBodyCodegen method generateFieldForSingleton.

private void generateFieldForSingleton() {
    if (isEnumEntry(descriptor) || isCompanionObject(descriptor))
        return;
    if (isNonCompanionObject(descriptor)) {
        StackValue.Field field = StackValue.singletonViaInstance(descriptor, typeMapper);
        v.newField(JvmDeclarationOriginKt.OtherOrigin(myClass), ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
        if (!state.getClassBuilderMode().generateBodies)
            return;
        // Invoke the object constructor but ignore the result because INSTANCE will be initialized in the first line of <init>
        InstructionAdapter v = createOrGetClInitCodegen().v;
        markLineNumberForElement(element.getPsiOrParent(), v);
        v.anew(classAsmType);
        v.invokespecial(classAsmType.getInternalName(), "<init>", "()V", false);
        return;
    }
    ClassDescriptor companionObjectDescriptor = descriptor.getCompanionObjectDescriptor();
    if (companionObjectDescriptor == null) {
        return;
    }
    @Nullable KtObjectDeclaration companionObject = CollectionsKt.firstOrNull(myClass.getCompanionObjects());
    StackValue.Field field = StackValue.singleton(companionObjectDescriptor, typeMapper);
    v.newField(JvmDeclarationOriginKt.OtherOrigin(companionObject == null ? myClass.getPsiOrParent() : companionObject), ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null);
}
Also used : InstructionAdapter(org.jetbrains.org.objectweb.asm.commons.InstructionAdapter) JavaClassDescriptor(org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor) Nullable(org.jetbrains.annotations.Nullable)

Example 33 with InstructionAdapter

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

the class FunctionCodegen method generateDelegateToMethodBody.

private static void generateDelegateToMethodBody(// -1 means to add additional this parameter on stack
int firstParamIndex, @NotNull MethodVisitor mv, @NotNull Method asmMethod, @NotNull String classToDelegateTo, int opcode, boolean isInterface) {
    InstructionAdapter iv = new InstructionAdapter(mv);
    Type[] argTypes = asmMethod.getArgumentTypes();
    // The first line of some package file is written to the line number attribute of a static delegate to allow to 'step into' it
    // This is similar to what javac does with bridge methods
    Label label = new Label();
    iv.visitLabel(label);
    iv.visitLineNumber(1, label);
    int paramIndex = firstParamIndex;
    if (paramIndex == -1) {
        iv.load(0, AsmTypes.OBJECT_TYPE);
        paramIndex = 1;
    }
    for (Type argType : argTypes) {
        iv.load(paramIndex, argType);
        paramIndex += argType.getSize();
    }
    iv.visitMethodInsn(opcode, classToDelegateTo, asmMethod.getName(), asmMethod.getDescriptor(), isInterface);
    iv.areturn(asmMethod.getReturnType());
}
Also used : KotlinType(org.jetbrains.kotlin.types.KotlinType) InstructionAdapter(org.jetbrains.org.objectweb.asm.commons.InstructionAdapter)

Example 34 with InstructionAdapter

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

the class FunctionCodegen method generateMethodBody.

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);
    KotlinTypeMapper typeMapper = parentCodegen.typeMapper;
    if (BuiltinSpecialBridgesUtil.shouldHaveTypeSafeBarrier(functionDescriptor, getSignatureMapper(typeMapper))) {
        generateTypeCheckBarrierIfNeeded(new InstructionAdapter(mv), functionDescriptor, signature.getReturnType(), /* delegateParameterTypes = */
        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 if (OwnerKind.DEFAULT_IMPLS == context.getContextKind() && isJvm8InterfaceWithDefaultsMember(functionDescriptor, parentCodegen.state)) {
        int flags = AsmUtil.getMethodAsmFlags(functionDescriptor, OwnerKind.DEFAULT_IMPLS, context.getState());
        assert (flags & Opcodes.ACC_ABSTRACT) == 0 : "Interface method with body should be non-abstract" + functionDescriptor;
        Type type = typeMapper.mapOwner(functionDescriptor);
        Method asmMethod = typeMapper.mapAsmMethod(functionDescriptor, OwnerKind.DEFAULT_IMPLS);
        generateDelegateToStaticMethodBody(true, mv, new Method(asmMethod.getName() + JvmAbi.DEFAULT_IMPLS_DELEGATE_SUFFIX, asmMethod.getDescriptor()), type.getInternalName());
        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 (!KotlinTypeMapper.isAccessor(functionDescriptor)) {
            genNotNullAssertionsForParameters(new InstructionAdapter(mv), parentCodegen.state, functionDescriptor, frameMap);
        }
        parentCodegen.beforeMethodBody(mv);
        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(), typeMapper, (functionFakeIndex >= 0 ? 1 : 0) + (lambdaFakeIndex >= 0 ? 1 : 0));
    //TODO: it's best to move all below logic to 'generateLocalVariableTable' method
    if (context.isInlineMethodContext() && functionFakeIndex != -1) {
        mv.visitLocalVariable(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION + typeMapper.mapAsmMethod(functionDescriptor).getName(), 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));
            KtPureElement functionArgument = parentCodegen.element;
            String functionName = "unknown";
            if (functionArgument instanceof KtFunction) {
                ValueParameterDescriptor inlineArgumentDescriptor = InlineUtil.getInlineArgumentDescriptor((KtFunction) functionArgument, parentCodegen.bindingContext);
                if (inlineArgumentDescriptor != null) {
                    functionName = inlineArgumentDescriptor.getContainingDeclaration().getName().asString();
                }
            }
            mv.visitLocalVariable(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT + lambdaOrdinal + "$" + functionName, Type.INT_TYPE.getDescriptor(), null, methodBegin, methodEnd, lambdaFakeIndex);
        }
    }
}
Also used : Method(org.jetbrains.org.objectweb.asm.commons.Method) KotlinType(org.jetbrains.kotlin.types.KotlinType) InstructionAdapter(org.jetbrains.org.objectweb.asm.commons.InstructionAdapter) KotlinTypeMapper(org.jetbrains.kotlin.codegen.state.KotlinTypeMapper)

Example 35 with InstructionAdapter

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

the class ImplementationBodyCodegen method initializeEnumConstant.

private void initializeEnumConstant(@NotNull List<KtEnumEntry> enumEntries, int ordinal) {
    ExpressionCodegen codegen = createOrGetClInitCodegen();
    InstructionAdapter iv = codegen.v;
    KtEnumEntry enumEntry = enumEntries.get(ordinal);
    iv.dup();
    iv.iconst(ordinal);
    ClassDescriptor classDescriptor = getNotNull(bindingContext, BindingContext.CLASS, enumEntry);
    Type implClass = typeMapper.mapClass(classDescriptor);
    iv.anew(implClass);
    iv.dup();
    iv.aconst(enumEntry.getName());
    iv.iconst(ordinal);
    List<KtSuperTypeListEntry> delegationSpecifiers = enumEntry.getSuperTypeListEntries();
    ResolvedCall<?> defaultArgumentsConstructorCall = CallUtilKt.getResolvedCall(enumEntry, bindingContext);
    boolean enumEntryHasSubclass = CodegenBinding.enumEntryNeedSubclass(bindingContext, classDescriptor);
    if (delegationSpecifiers.size() == 1 && !enumEntryNeedSubclass(bindingContext, enumEntry)) {
        ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(delegationSpecifiers.get(0), bindingContext);
        CallableMethod method = typeMapper.mapToCallableMethod((ConstructorDescriptor) resolvedCall.getResultingDescriptor(), false);
        codegen.invokeMethodWithArguments(method, resolvedCall, StackValue.none());
    } else if (defaultArgumentsConstructorCall != null && !enumEntryHasSubclass) {
        codegen.invokeFunction(defaultArgumentsConstructorCall, StackValue.none()).put(Type.VOID_TYPE, iv);
    } else {
        iv.invokespecial(implClass.getInternalName(), "<init>", "(Ljava/lang/String;I)V", false);
    }
    iv.dup();
    iv.putstatic(classAsmType.getInternalName(), enumEntry.getName(), classAsmType.getDescriptor());
    iv.astore(OBJECT_TYPE);
}
Also used : Type(org.jetbrains.org.objectweb.asm.Type) KotlinType(org.jetbrains.kotlin.types.KotlinType) Type.getObjectType(org.jetbrains.org.objectweb.asm.Type.getObjectType) InstructionAdapter(org.jetbrains.org.objectweb.asm.commons.InstructionAdapter) JavaClassDescriptor(org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor)

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