diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FieldInfo.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FieldInfo.java index 9c0bcbdcdb9..0f5e6503836 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FieldInfo.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FieldInfo.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.codegen.state.JetTypeMapper; import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.ClassKind; +import org.jetbrains.kotlin.descriptors.ClassifierDescriptor; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.resolve.DescriptorUtils; import org.jetbrains.org.objectweb.asm.Type; @@ -44,6 +45,18 @@ public class FieldInfo { } } + @SuppressWarnings("deprecation") + @NotNull + public static FieldInfo deprecatedFieldForClassObject(@NotNull ClassDescriptor classObject, @NotNull JetTypeMapper typeMapper) { + assert DescriptorUtils.isClassObject(classObject) : "Not a class object: " + classObject; + return new FieldInfo( + typeMapper.mapType((ClassifierDescriptor) classObject.getContainingDeclaration()), + typeMapper.mapType(classObject), + JvmAbi.DEPRECATED_CLASS_OBJECT_FIELD, + true + ); + } + @NotNull public static FieldInfo createForHiddenField(@NotNull Type owner, @NotNull Type fieldType, @NotNull String fieldName) { return new FieldInfo(owner, fieldType, fieldName, false); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index 96e7a28ea06..934f2849390 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -37,6 +37,7 @@ import org.jetbrains.kotlin.lexer.JetTokens; import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.load.java.JvmAnnotationNames; import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor; +import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; @@ -961,7 +962,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (isEnumEntry(descriptor) || isClassObject(descriptor)) return; if (isObject(descriptor)) { - createFieldForSingleton(descriptor, myClass); + StackValue.Field field = StackValue.singleton(descriptor, typeMapper); + v.newField(OtherOrigin(myClass), ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null); if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; @@ -980,7 +982,14 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { JetObjectDeclaration classObject = ((JetClass) myClass).getClassObject(); assert classObject != null : "Class object not found: " + myClass.getText(); - createFieldForSingleton(classObjectDescriptor, classObject); + StackValue.Field field = StackValue.singleton(classObjectDescriptor, typeMapper); + v.newField(OtherOrigin(classObject), ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null); + + StackValue.Field deprecatedField = StackValue.deprecatedClassObjectAccessor(classObjectDescriptor, typeMapper); + FieldVisitor fv = v.newField(OtherOrigin(classObject), ACC_PUBLIC | ACC_STATIC | ACC_FINAL | ACC_DEPRECATED, + deprecatedField.name, deprecatedField.type.getDescriptor(), null, null); + + fv.visitAnnotation(asmDescByFqNameWithoutInnerClasses(new FqName("java.lang.Deprecated")), true).visitEnd(); if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return; @@ -989,12 +998,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } - private void createFieldForSingleton(@NotNull ClassDescriptor fieldTypeDescriptor, @NotNull JetClassOrObject original) { - StackValue.Field field = StackValue.singleton(fieldTypeDescriptor, typeMapper); - - v.newField(OtherOrigin(original), ACC_PUBLIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null); - } - private void generateClassObjectBackingFieldCopies() { if (classObjectPropertiesToCopy == null) return; @@ -1044,7 +1047,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { ExpressionCodegen codegen = createOrGetClInitCodegen(); FunctionDescriptor constructor = codegen.accessibleFunctionDescriptor(KotlinPackage.single(classObject.getConstructors())); generateMethodCallTo(constructor, codegen.v); - StackValue.singleton(classObject, typeMapper).store(StackValue.onStack(typeMapper.mapClass(classObject)), codegen.v, true); + codegen.v.dup(); + StackValue instance = StackValue.onStack(typeMapper.mapClass(classObject)); + StackValue.singleton(classObject, typeMapper).store(instance, codegen.v, true); + StackValue.deprecatedClassObjectAccessor(classObject, typeMapper).store(instance, codegen.v, true); } private void generatePrimaryConstructor(final DelegationFieldsInfo delegationFieldsInfo) { @@ -1131,7 +1137,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (isClassObjectWithBackingFieldsInOuter(descriptor)) { final ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen(); - //generate OBJECT$ parentCodegen.generateClassObjectInitializer(descriptor); generateInitializers(new Function0() { @Override diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index bd772d304fd..fe55f1c692d 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -206,6 +206,10 @@ public abstract class StackValue { return new Field(field.type, field.owner, field.name, field.isStaticPut, newReceiver); } + @NotNull + private static Field field(@NotNull FieldInfo info) { + return field(info.getFieldType(), Type.getObjectType(info.getOwnerInternalName()), info.getFieldName(), true, none()); + } @NotNull public static StackValue changeReceiverForFieldAndSharedVar(@NotNull StackValueWithSimpleReceiver stackValue, @Nullable StackValue newReceiver) { @@ -506,8 +510,11 @@ public abstract class StackValue { } public static Field singleton(ClassDescriptor classDescriptor, JetTypeMapper typeMapper) { - FieldInfo info = FieldInfo.createForSingleton(classDescriptor, typeMapper); - return field(info.getFieldType(), Type.getObjectType(info.getOwnerInternalName()), info.getFieldName(), true, none()); + return field(FieldInfo.createForSingleton(classDescriptor, typeMapper)); + } + + public static Field deprecatedClassObjectAccessor(ClassDescriptor classDescriptor, JetTypeMapper typeMapper) { + return field(FieldInfo.deprecatedFieldForClassObject(classDescriptor, typeMapper)); } public static StackValue operation(Type type, Function1 lambda) { diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java index ca1e6b43ef1..3cc449275a0 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAbi.java @@ -45,6 +45,10 @@ public final class JvmAbi { public static final String KOTLIN_CLASS_FIELD_NAME = "$kotlinClass"; public static final String KOTLIN_PACKAGE_FIELD_NAME = "$kotlinPackage"; + //TODO: To be removed after kotlin M11 + @Deprecated + public static final String DEPRECATED_CLASS_OBJECT_FIELD = "OBJECT$"; + @NotNull public static String getSyntheticMethodNameForAnnotatedProperty(@NotNull Name propertyName) { return propertyName.asString() + ANNOTATED_PROPERTY_METHOD_NAME_SUFFIX;