diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java index d74a8f7d62a..ea7b46873ed 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/AnnotationCodegen.java @@ -67,11 +67,11 @@ public abstract class AnnotationCodegen { private static final AnnotationVisitor NO_ANNOTATION_VISITOR = new AnnotationVisitor(Opcodes.ASM5) {}; - private final MemberCodegen memberCodegen; + private final InnerClassConsumer innerClassConsumer; private final KotlinTypeMapper typeMapper; - private AnnotationCodegen(@NotNull MemberCodegen memberCodegen, @NotNull KotlinTypeMapper mapper) { - this.memberCodegen = memberCodegen; + private AnnotationCodegen(@NotNull InnerClassConsumer innerClassConsumer, @NotNull KotlinTypeMapper mapper) { + this.innerClassConsumer = innerClassConsumer; this.typeMapper = mapper; } @@ -288,7 +288,7 @@ public abstract class AnnotationCodegen { String descriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor(); if (classifierDescriptor instanceof ClassDescriptor) { - memberCodegen.addInnerClassInfoFromAnnotation(((ClassDescriptor) classifierDescriptor)); + innerClassConsumer.addInnerClassInfoFromAnnotation(((ClassDescriptor) classifierDescriptor)); } AnnotationVisitor annotationVisitor = visitAnnotation(descriptor, rp == RetentionPolicy.RUNTIME); @@ -486,10 +486,10 @@ public abstract class AnnotationCodegen { public static AnnotationCodegen forClass( final @NotNull ClassVisitor cv, - @NotNull MemberCodegen memberCodegen, + @NotNull InnerClassConsumer innerClassConsumer, @NotNull KotlinTypeMapper mapper ) { - return new AnnotationCodegen(memberCodegen, mapper) { + return new AnnotationCodegen(innerClassConsumer, mapper) { @NotNull @Override AnnotationVisitor visitAnnotation(String descr, boolean visible) { @@ -500,10 +500,10 @@ public abstract class AnnotationCodegen { public static AnnotationCodegen forMethod( final @NotNull MethodVisitor mv, - @NotNull MemberCodegen memberCodegen, + @NotNull InnerClassConsumer innerClassConsumer, @NotNull KotlinTypeMapper mapper ) { - return new AnnotationCodegen(memberCodegen, mapper) { + return new AnnotationCodegen(innerClassConsumer, mapper) { @NotNull @Override AnnotationVisitor visitAnnotation(String descr, boolean visible) { @@ -514,10 +514,10 @@ public abstract class AnnotationCodegen { public static AnnotationCodegen forField( final @NotNull FieldVisitor fv, - @NotNull MemberCodegen memberCodegen, + @NotNull InnerClassConsumer innerClassConsumer, @NotNull KotlinTypeMapper mapper ) { - return new AnnotationCodegen(memberCodegen, mapper) { + return new AnnotationCodegen(innerClassConsumer, mapper) { @NotNull @Override AnnotationVisitor visitAnnotation(String descr, boolean visible) { @@ -529,10 +529,10 @@ public abstract class AnnotationCodegen { public static AnnotationCodegen forParameter( final int parameter, final @NotNull MethodVisitor mv, - @NotNull MemberCodegen memberCodegen, + @NotNull InnerClassConsumer innerClassConsumer, @NotNull KotlinTypeMapper mapper ) { - return new AnnotationCodegen(memberCodegen, mapper) { + return new AnnotationCodegen(innerClassConsumer, mapper) { @NotNull @Override AnnotationVisitor visitAnnotation(String descr, boolean visible) { @@ -543,10 +543,10 @@ public abstract class AnnotationCodegen { public static AnnotationCodegen forAnnotationDefaultValue( final @NotNull MethodVisitor mv, - @NotNull MemberCodegen memberCodegen, + @NotNull InnerClassConsumer innerClassConsumer, @NotNull KotlinTypeMapper mapper ) { - return new AnnotationCodegen(memberCodegen, mapper) { + return new AnnotationCodegen(innerClassConsumer, mapper) { @NotNull @Override AnnotationVisitor visitAnnotation(String descr, boolean visible) { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java index 9662574c300..712381b324a 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FunctionCodegen.java @@ -272,7 +272,17 @@ public class FunctionCodegen { Method asmMethod, MethodVisitor mv ) { - AnnotationCodegen annotationCodegen = AnnotationCodegen.forMethod(mv, memberCodegen, typeMapper); + generateMethodAnnotations(functionDescriptor, asmMethod, mv, memberCodegen, typeMapper); + } + + public static void generateMethodAnnotations( + @NotNull FunctionDescriptor functionDescriptor, + Method asmMethod, + MethodVisitor mv, + @NotNull InnerClassConsumer consumer, + @NotNull KotlinTypeMapper typeMapper + ) { + AnnotationCodegen annotationCodegen = AnnotationCodegen.forMethod(mv, consumer, typeMapper); if (functionDescriptor instanceof PropertyAccessorDescriptor) { AnnotationUseSiteTarget target = functionDescriptor instanceof PropertySetterDescriptor ? PROPERTY_SETTER : PROPERTY_GETTER; @@ -288,6 +298,17 @@ public class FunctionCodegen { @NotNull MethodVisitor mv, @NotNull JvmMethodSignature jvmSignature ) { + generateParameterAnnotations(functionDescriptor, mv, jvmSignature, memberCodegen, state); + } + + public static void generateParameterAnnotations( + @NotNull FunctionDescriptor functionDescriptor, + @NotNull MethodVisitor mv, + @NotNull JvmMethodSignature jvmSignature, + @NotNull InnerClassConsumer innerClassConsumer, + @NotNull GenerationState state + ) { + KotlinTypeMapper typeMapper = state.getTypeMapper(); Iterator iterator = functionDescriptor.getValueParameters().iterator(); List kotlinParameterTypes = jvmSignature.getValueParameters(); @@ -295,13 +316,13 @@ public class FunctionCodegen { JvmMethodParameterSignature parameterSignature = kotlinParameterTypes.get(i); JvmMethodParameterKind kind = parameterSignature.getKind(); if (kind.isSkippedInGenericSignature()) { - markEnumOrInnerConstructorParameterAsSynthetic(mv, i); + markEnumOrInnerConstructorParameterAsSynthetic(mv, i, state.getClassBuilderMode()); continue; } if (kind == JvmMethodParameterKind.VALUE) { ValueParameterDescriptor parameter = iterator.next(); - AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, memberCodegen, typeMapper); + AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, innerClassConsumer, typeMapper); if (functionDescriptor instanceof PropertySetterDescriptor) { PropertyDescriptor propertyDescriptor = ((PropertySetterDescriptor) functionDescriptor).getCorrespondingProperty(); @@ -320,7 +341,7 @@ public class FunctionCodegen { ReceiverParameterDescriptor receiver = JvmCodegenUtil.getDirectMember(functionDescriptor).getExtensionReceiverParameter(); if (receiver != null) { - AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, memberCodegen, typeMapper); + AnnotationCodegen annotationCodegen = AnnotationCodegen.forParameter(i, mv, innerClassConsumer, typeMapper); Annotated targetedAnnotations = new AnnotatedWithOnlyTargetedAnnotations(receiver.getType()); annotationCodegen.genAnnotations(targetedAnnotations, parameterSignature.getAsmType(), RECEIVER); @@ -330,9 +351,9 @@ public class FunctionCodegen { } } - private void markEnumOrInnerConstructorParameterAsSynthetic(MethodVisitor mv, int i) { + private static void markEnumOrInnerConstructorParameterAsSynthetic(MethodVisitor mv, int i, ClassBuilderMode mode) { // IDEA's ClsPsi builder fails to annotate synthetic parameters - if (state.getClassBuilderMode() == ClassBuilderMode.LIGHT_CLASSES) return; + if (mode == ClassBuilderMode.LIGHT_CLASSES) return; // This is needed to avoid RuntimeInvisibleParameterAnnotations error in javac: // see MethodWriter.visitParameterAnnotation() diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/InnerClassConsumer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/InnerClassConsumer.kt new file mode 100644 index 00000000000..3f41e8d50c7 --- /dev/null +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/InnerClassConsumer.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.codegen + +import org.jetbrains.kotlin.descriptors.ClassDescriptor + +interface InnerClassConsumer { + fun addInnerClassInfoFromAnnotation(classDescriptor: ClassDescriptor) +} \ No newline at end of file diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 6778a676c3c..53b1a10db0c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -73,7 +73,7 @@ import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin. import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt.Synthetic; import static org.jetbrains.org.objectweb.asm.Opcodes.*; -public abstract class MemberCodegen { +public abstract class MemberCodegen implements InnerClassConsumer { protected final GenerationState state; protected final T element; protected final FieldOwnerContext context; @@ -304,6 +304,7 @@ public abstract class MemberCodegen() @@ -69,6 +70,7 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac signature.superclassName, signature.interfaces.toTypedArray() ) + AnnotationCodegen.forClass(visitor.visitor, this, typeMapper).genAnnotations(descriptor, null) irClass.declarations.forEach { generateDeclaration(it) @@ -121,8 +123,15 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac fun generateField(field: IrField) { val fieldType = typeMapper.mapType(field.descriptor) val fieldSignature = typeMapper.mapFieldSignature(field.descriptor.type, field.descriptor) - visitor.newField(field.OtherOrigin, field.descriptor.calculateCommonFlags(), field.descriptor.name.asString(), fieldType.descriptor, - fieldSignature, null/*TODO support default values*/) + val fv = visitor.newField(field.OtherOrigin, field.descriptor.calculateCommonFlags(), field.descriptor.name.asString(), fieldType.descriptor, + fieldSignature, null/*TODO support default values*/) + + if (field.origin == JvmLoweredDeclarationOrigin.FIELD_FOR_ENUM_ENTRY) { + AnnotationCodegen.forField(fv, this, typeMapper).genAnnotations(field.descriptor, null) + } + else { + + } } fun generateMethod(method: IrFunction) { @@ -157,6 +166,18 @@ class ClassCodegen private constructor(val irClass: IrClass, val context: JvmBac return if (parentClassCodegen != null) descriptor else null } + // It's necessary for proper recovering of classId by plain string JVM descriptor when loading annotations + // See FileBasedKotlinClass.convertAnnotationVisitor + override fun addInnerClassInfoFromAnnotation(classDescriptor: ClassDescriptor) { + var current: DeclarationDescriptor? = classDescriptor + while (current != null && !isTopLevelDeclaration(current)) { + if (current is ClassDescriptor) { + innerClasses.add(current) + } + current = current.containingDeclaration + } + } + } fun ClassDescriptor.calculateClassFlags(): Int { diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt index 11723ee88a8..349ede85691 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/ExpressionCodegen.kt @@ -313,11 +313,16 @@ class ExpressionCodegen( } private fun generateLocal(descriptor: CallableDescriptor, type: Type): StackValue { + val index = findLocalIndex(descriptor) + StackValue.local(index, type).put(type, mv) + return onStack(type) + } + + private fun findLocalIndex(descriptor: CallableDescriptor): Int { val index = frame.getIndex(descriptor).apply { if (this < 0) throw AssertionError("Non-mapped local variable descriptor: $descriptor") } - StackValue.local(index, type).put(type, mv) - return onStack(type) + return index } override fun visitGetObjectValue(expression: IrGetObjectValue, data: BlockInfo): StackValue { @@ -330,7 +335,7 @@ class ExpressionCodegen( override fun visitSetVariable(expression: IrSetVariable, data: BlockInfo): StackValue { val value = expression.value.accept(this, data) - StackValue.local(frame.getIndex(expression.descriptor), expression.descriptor.asmType).store(value, mv) + StackValue.local(findLocalIndex(expression.descriptor), expression.descriptor.asmType).store(value, mv) return none() } @@ -494,8 +499,8 @@ class ExpressionCodegen( val end = Label() thenBranch.apply { - gen(this, data) - coerceNotToUnit(this.asmType, type) + gen(this, type, data) + //coerceNotToUnit(this.asmType, type) } mv.goTo(end) diff --git a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt index 1f5751b40dc..a8bcf96156c 100644 --- a/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt +++ b/compiler/ir/backend.jvm/src/org/jetbrains/kotlin/backend/jvm/codegen/FunctionCodegen.kt @@ -17,16 +17,13 @@ package org.jetbrains.kotlin.backend.jvm.codegen import org.jetbrains.kotlin.backend.jvm.lower.InitializersLowering -import org.jetbrains.kotlin.codegen.AsmUtil +import org.jetbrains.kotlin.codegen.* import org.jetbrains.kotlin.codegen.AsmUtil.isStaticMethod -import org.jetbrains.kotlin.codegen.FrameMap -import org.jetbrains.kotlin.codegen.JvmCodegenUtil -import org.jetbrains.kotlin.codegen.OwnerKind +import org.jetbrains.kotlin.codegen.FunctionCodegen import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.ir.declarations.IrFunction -import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind @@ -60,6 +57,9 @@ class FunctionCodegen(val irFunction: IrFunction, val classCodegen: ClassCodegen signature.asmMethod.name, signature.asmMethod.descriptor, signature.genericsSignature, null/*TODO support exception*/) + FunctionCodegen.generateMethodAnnotations(descriptor, signature.asmMethod, methodVisitor, classCodegen, state.typeMapper) + FunctionCodegen.generateParameterAnnotations(descriptor, methodVisitor, signature, classCodegen, state) + if (!state.classBuilderMode.generateBodies || flags.and(Opcodes.ACC_ABSTRACT) != 0) { methodVisitor.visitEnd() return