From b73be50e5b2ea5e1556673e0762fc19395f416c1 Mon Sep 17 00:00:00 2001 From: Mikhael Bogdanov Date: Tue, 14 Mar 2017 13:52:07 +0100 Subject: [PATCH] Move object initialization from to Codegen generates static backing fields for object properties. They are initialized in class constructor but some of them are final static and such access is prohibited in specification but it's allowed in java bytecode <= 1.8. Such access in 1.9 bytecode cause "IllegalAccessError: Update to static final field Object.INSTANCE attempted from a different method () than the initializer method " Added additional hidden field in interface companion to pass out companion instance from . #KT-15894 Fixed --- .../jetbrains/kotlin/codegen/FieldInfo.java | 7 +- .../codegen/ImplementationBodyCodegen.java | 103 ++++++++++++------ .../jetbrains/kotlin/codegen/StackValue.java | 4 +- .../codegen/box/objects/classCompanion.kt | 19 ++++ .../codegen/box/objects/interfaceCompanion.kt | 19 ++++ .../testData/codegen/box/objects/object.kt | 15 +++ .../enclosing/lambdaInObjectDeclaration.kt | 2 +- .../codegen/dumpDeclarations/interfaces.json | 15 ++- .../ir/IrBlackBoxCodegenTestGenerated.java | 18 +++ .../codegen/BlackBoxCodegenTestGenerated.java | 18 +++ .../LightAnalysisModeTestGenerated.java | 18 +++ .../jetbrains/kotlin/load/java/JvmAbi.java | 14 ++- .../semantics/JsCodegenBoxTestGenerated.java | 18 +++ 13 files changed, 223 insertions(+), 47 deletions(-) create mode 100644 compiler/testData/codegen/box/objects/classCompanion.kt create mode 100644 compiler/testData/codegen/box/objects/interfaceCompanion.kt create mode 100644 compiler/testData/codegen/box/objects/object.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/FieldInfo.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/FieldInfo.java index 363f313d07f..adc32f8b538 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/FieldInfo.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/FieldInfo.java @@ -34,7 +34,7 @@ public class FieldInfo { } if (isNonCompanionObject(classDescriptor) || CompanionObjectMapping.INSTANCE.isMappedIntrinsicCompanionObject(classDescriptor)) { - return createSingletonViaInstance(classDescriptor, typeMapper); + return createSingletonViaInstance(classDescriptor, typeMapper, JvmAbi.INSTANCE_FIELD); } ClassDescriptor ownerDescriptor = DescriptorUtils.getParentOfType(classDescriptor, ClassDescriptor.class); @@ -46,10 +46,11 @@ public class FieldInfo { @NotNull public static FieldInfo createSingletonViaInstance( @NotNull ClassDescriptor classDescriptor, - @NotNull KotlinTypeMapper typeMapper + @NotNull KotlinTypeMapper typeMapper, + @NotNull String name ) { Type type = typeMapper.mapType(classDescriptor); - return new FieldInfo(type, type, JvmAbi.INSTANCE_FIELD, true); + return new FieldInfo(type, type, name, true); } @NotNull diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java index e1cb8cf1f11..9fcc02e1c16 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ImplementationBodyCodegen.java @@ -39,7 +39,6 @@ import org.jetbrains.kotlin.config.LanguageFeature; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.incremental.components.NoLookupLocation; import org.jetbrains.kotlin.lexer.KtTokens; -import org.jetbrains.kotlin.load.java.JvmAbi; import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor; import org.jetbrains.kotlin.load.kotlin.TypeMappingMode; import org.jetbrains.kotlin.name.ClassId; @@ -77,6 +76,7 @@ import static org.jetbrains.kotlin.codegen.CodegenUtilKt.isNonGenericToArray; import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.*; import static org.jetbrains.kotlin.codegen.binding.CodegenBinding.enumEntryNeedSubclass; import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtils2Kt.initDefaultSourceMappingIfNeeded; +import static org.jetbrains.kotlin.load.java.JvmAbi.*; import static org.jetbrains.kotlin.resolve.BindingContextUtils.getDelegationConstructorCall; import static org.jetbrains.kotlin.resolve.BindingContextUtils.getNotNull; import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.descriptorToDeclaration; @@ -354,6 +354,8 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { protected void generateSyntheticPartsAfterBody() { generateFieldForSingleton(); + initializeObjects(); + generateCompanionObjectBackingFieldCopies(); generateTraitMethods(); @@ -811,21 +813,21 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } private void generateFieldForSingleton() { + if (isCompanionObjectInInterfaceNotIntrinsic(descriptor)) { + StackValue.Field field = StackValue.createSingletonViaInstance(descriptor, typeMapper, HIDDEN_INSTANCE_FIELD); + //hidden instance in interface companion + v.newField(JvmDeclarationOriginKt.OtherOrigin(descriptor), + ACC_SYNTHETIC | ACC_STATIC | ACC_FINAL, field.name, field.type.getDescriptor(), null, null); + } + if (isEnumEntry(descriptor) || isCompanionObject(descriptor)) return; if (isNonCompanionObject(descriptor)) { - StackValue.Field field = StackValue.singletonViaInstance(descriptor, typeMapper); + StackValue.Field field = StackValue.createSingletonViaInstance(descriptor, typeMapper, INSTANCE_FIELD); v.newField(JvmDeclarationOriginKt.OtherOriginFromPure(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 - InstructionAdapter v = createOrGetClInitCodegen().v; - markLineNumberForElement(element.getPsiOrParent(), v); - v.anew(classAsmType); - v.invokespecial(classAsmType.getInternalName(), "", "()V", false); - return; } @@ -853,6 +855,60 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { } } + private void initializeObjects() { + if (!DescriptorUtils.isObject(descriptor)) return; + if (!state.getClassBuilderMode().generateBodies) return; + + boolean isNonCompanionObject = isNonCompanionObject(descriptor); + boolean isInterfaceCompanion = isCompanionObjectInInterfaceNotIntrinsic(descriptor); + boolean isMappedIntrinsicCompanionObject = isMappedIntrinsicCompanionObject(descriptor); + if (isNonCompanionObject || isInterfaceCompanion || isMappedIntrinsicCompanionObject) { + ExpressionCodegen clInitCodegen = createOrGetClInitCodegen(); + InstructionAdapter v = clInitCodegen.v; + markLineNumberForElement(element.getPsiOrParent(), v); + v.anew(classAsmType); + v.dup(); + v.invokespecial(classAsmType.getInternalName(), "", "()V", false); + + //local0 emulates this in object constructor + int local0Index = clInitCodegen.getFrameMap().enterTemp(classAsmType); + assert local0Index == 0 : "Local variable with index 0 in clInit should be used only for singleton instance keeping"; + StackValue.Local local0 = StackValue.local(0, classAsmType); + local0.store(StackValue.onStack(classAsmType), clInitCodegen.v); + StackValue.Field singleton = + StackValue.createSingletonViaInstance( + descriptor, typeMapper, isInterfaceCompanion ? HIDDEN_INSTANCE_FIELD : INSTANCE_FIELD + ); + singleton.store(local0, clInitCodegen.v); + + generateInitializers(clInitCodegen); + + if (isInterfaceCompanion) { + //initialize singleton instance in outer by hidden instance + StackValue.singleton(descriptor, typeMapper).store( + singleton, getParentCodegen().createOrGetClInitCodegen().v, true + ); + } + } + else if (isCompanionObjectWithBackingFieldsInOuter(descriptor)) { + ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen(); + ExpressionCodegen parentClInitCodegen = parentCodegen.createOrGetClInitCodegen(); + InstructionAdapter parentVisitor = parentClInitCodegen.v; + + FunctionDescriptor constructor = (FunctionDescriptor) parentCodegen.context.accessibleDescriptor( + CollectionsKt.single(descriptor.getConstructors()), /* superCallExpression = */ null + ); + parentCodegen.generateMethodCallTo(constructor, null, parentVisitor); + StackValue instance = StackValue.onStack(parentCodegen.typeMapper.mapClass(descriptor)); + StackValue.singleton(descriptor, parentCodegen.typeMapper).store(instance, parentVisitor, true); + + generateInitializers(parentClInitCodegen); + } + else { + assert false : "Unknown object type: " + descriptor; + } + } + private void generateCompanionObjectBackingFieldCopies() { if (companionObjectPropertiesToCopy == null) return; @@ -900,17 +956,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { field.store(property, codegen.v); } - private void generateCompanionObjectInitializer(@NotNull ClassDescriptor companionObject) { - ExpressionCodegen codegen = createOrGetClInitCodegen(); - - FunctionDescriptor constructor = (FunctionDescriptor) context.accessibleDescriptor( - CollectionsKt.single(companionObject.getConstructors()), /* superCallExpression = */ null - ); - generateMethodCallTo(constructor, null, codegen.v); - StackValue instance = StackValue.onStack(typeMapper.mapClass(companionObject)); - StackValue.singleton(companionObject, typeMapper).store(instance, codegen.v, true); - } - private void generatePrimaryConstructor(DelegationFieldsInfo delegationFieldsInfo) { if (isInterface(descriptor) || isAnnotationClass(descriptor)) return; @@ -978,10 +1023,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { generateDelegatorToConstructorCall(iv, codegen, constructorDescriptor, getDelegationConstructorCall(bindingContext, constructorDescriptor)); - if (isNonCompanionObject(descriptor)) { - StackValue.singletonViaInstance(descriptor, typeMapper).store(StackValue.LOCAL_0, iv); - } - for (KtSuperTypeListEntry specifier : myClass.getSuperTypeListEntries()) { if (specifier instanceof KtDelegatedSuperTypeEntry) { genCallToDelegatorByExpressionSpecifier(iv, codegen, (KtDelegatedSuperTypeEntry) specifier, fieldsInfo); @@ -1003,18 +1044,10 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { curParam++; } - if (isCompanionObject(descriptor)) { - ImplementationBodyCodegen parentCodegen = (ImplementationBodyCodegen) getParentCodegen(); - parentCodegen.generateCompanionObjectInitializer(descriptor); - } - - if (JvmAbi.isCompanionObjectWithBackingFieldsInOuter(descriptor)) { - generateInitializers(((ImplementationBodyCodegen) getParentCodegen())::createOrGetClInitCodegen); - } - else { + //object initialization was moved to initializeObjects() + if (!isObject(descriptor)) { generateInitializers(codegen); } - iv.visitInsn(RETURN); } @@ -1159,7 +1192,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen { if (asmType == null) continue; - result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, JvmAbi.DELEGATE_SUPER_FIELD_PREFIX + n); + result.addField((KtDelegatedSuperTypeEntry) specifier, asmType, DELEGATE_SUPER_FIELD_PREFIX + n); } n++; } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java index 7fbb9ed385c..11193c5aaf4 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/StackValue.java @@ -621,8 +621,8 @@ public abstract class StackValue { return field(FieldInfo.createForSingleton(classDescriptor, typeMapper), none()); } - public static Field singletonViaInstance(ClassDescriptor classDescriptor, KotlinTypeMapper typeMapper) { - return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper), none()); + public static Field createSingletonViaInstance(@NotNull ClassDescriptor classDescriptor, @NotNull KotlinTypeMapper typeMapper, @NotNull String name) { + return field(FieldInfo.createSingletonViaInstance(classDescriptor, typeMapper, name), none()); } public static StackValue operation(Type type, Function1 lambda) { diff --git a/compiler/testData/codegen/box/objects/classCompanion.kt b/compiler/testData/codegen/box/objects/classCompanion.kt new file mode 100644 index 00000000000..66d6d588238 --- /dev/null +++ b/compiler/testData/codegen/box/objects/classCompanion.kt @@ -0,0 +1,19 @@ +var result = "" + +class A { + + companion object { + + val prop = test() + + fun test(): String { + result += "OK" + return result + } + } +} + +fun box(): String { + if (A.prop != "OK") return "fail ${A.prop}" + return result +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/objects/interfaceCompanion.kt b/compiler/testData/codegen/box/objects/interfaceCompanion.kt new file mode 100644 index 00000000000..924329d3b37 --- /dev/null +++ b/compiler/testData/codegen/box/objects/interfaceCompanion.kt @@ -0,0 +1,19 @@ +var result = "" + +interface A { + + companion object { + + val prop = test() + + fun test(): String { + result += "OK" + return result + } + } +} + +fun box(): String { + if (A.prop != "OK") return "fail ${A.prop}" + return result +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/objects/object.kt b/compiler/testData/codegen/box/objects/object.kt new file mode 100644 index 00000000000..8ce9ee1c9ba --- /dev/null +++ b/compiler/testData/codegen/box/objects/object.kt @@ -0,0 +1,15 @@ +var result = "" + +object A { + val prop = test() + + fun test(): String { + result += "OK" + return result + } +} + +fun box(): String { + if (A.prop != "OK") return "fail ${A.prop}" + return result +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/reflection/enclosing/lambdaInObjectDeclaration.kt b/compiler/testData/codegen/box/reflection/enclosing/lambdaInObjectDeclaration.kt index de061c4090a..9025828aa11 100644 --- a/compiler/testData/codegen/box/reflection/enclosing/lambdaInObjectDeclaration.kt +++ b/compiler/testData/codegen/box/reflection/enclosing/lambdaInObjectDeclaration.kt @@ -14,7 +14,7 @@ fun box(): String { if (enclosingMethod != null) return "method: $enclosingMethod" val enclosingConstructor = javaClass.getEnclosingConstructor() - if (enclosingConstructor == null) return "no enclosing constructor" + if (enclosingConstructor != null) return "field should be initialized in clInit" val enclosingClass = javaClass.getEnclosingClass() if (enclosingClass?.getName() != "O") return "enclosing class: $enclosingClass" diff --git a/compiler/testData/codegen/dumpDeclarations/interfaces.json b/compiler/testData/codegen/dumpDeclarations/interfaces.json index e4e86651b02..b9a10a0e879 100644 --- a/compiler/testData/codegen/dumpDeclarations/interfaces.json +++ b/compiler/testData/codegen/dumpDeclarations/interfaces.json @@ -49,7 +49,8 @@ "class": "PublicInterface$Companion", "members": [ {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "()V"}, - {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"} + {"visibility": "public", "declaration": "companion object", "name": "$$INSTANCE", "desc": "LPublicInterface$Companion;"}, + {"visibility": "public", "declaration": "companion object", "name": "", "desc": "()V"} ] }, { @@ -75,7 +76,8 @@ "class": "InternalInterface$Companion", "members": [ {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "()V"}, - {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"} + {"visibility": "public", "declaration": "companion object", "name": "$$INSTANCE", "desc": "LInternalInterface$Companion;"}, + {"visibility": "public", "declaration": "companion object", "name": "", "desc": "()V"} ] }, { @@ -101,7 +103,8 @@ "class": "InternalInterfacePrivateCompanion$Companion", "members": [ {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "()V"}, - {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"} + {"visibility": "private", "declaration": "companion object", "name": "$$INSTANCE", "desc": "LInternalInterfacePrivateCompanion$Companion;"}, + {"visibility": "private", "declaration": "companion object", "name": "", "desc": "()V"} ] }, { @@ -163,7 +166,8 @@ "class": "PrivateInterface$Companion", "members": [ {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "()V"}, - {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"} + {"visibility": "public", "declaration": "companion object", "name": "$$INSTANCE", "desc": "LPrivateInterface$Companion;"}, + {"visibility": "public", "declaration": "companion object", "name": "", "desc": "()V"} ] }, { @@ -189,7 +193,8 @@ "class": "PrivateInterfacePrivateCompanion$Companion", "members": [ {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "()V"}, - {"visibility": "private", "declaration": "constructor Companion()", "name": "", "desc": "(Lkotlin/jvm/internal/DefaultConstructorMarker;)V"} + {"visibility": "private", "declaration": "companion object", "name": "$$INSTANCE", "desc": "LPrivateInterfacePrivateCompanion$Companion;"}, + {"visibility": "private", "declaration": "companion object", "name": "", "desc": "()V"} ] }, { diff --git a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 47d623809e6..e7ce3771971 100644 --- a/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-ir-jvm/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -11993,6 +11993,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("classCompanion.kt") + public void testClassCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/classCompanion.kt"); + doTest(fileName); + } + @TestMetadata("flist.kt") public void testFlist() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt"); @@ -12011,6 +12017,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("interfaceCompanion.kt") + public void testInterfaceCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/interfaceCompanion.kt"); + doTest(fileName); + } + @TestMetadata("kt1047.kt") public void testKt1047() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/kt1047.kt"); @@ -12149,6 +12161,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes doTest(fileName); } + @TestMetadata("object.kt") + public void testObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/object.kt"); + doTest(fileName); + } + @TestMetadata("objectExtendsInnerAndReferencesOuterMember.kt") public void testObjectExtendsInnerAndReferencesOuterMember() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/objectExtendsInnerAndReferencesOuterMember.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 63f0e74f49e..bbc03016e9d 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -11993,6 +11993,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("classCompanion.kt") + public void testClassCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/classCompanion.kt"); + doTest(fileName); + } + @TestMetadata("flist.kt") public void testFlist() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt"); @@ -12011,6 +12017,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("interfaceCompanion.kt") + public void testInterfaceCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/interfaceCompanion.kt"); + doTest(fileName); + } + @TestMetadata("kt1047.kt") public void testKt1047() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/kt1047.kt"); @@ -12149,6 +12161,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { doTest(fileName); } + @TestMetadata("object.kt") + public void testObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/object.kt"); + doTest(fileName); + } + @TestMetadata("objectExtendsInnerAndReferencesOuterMember.kt") public void testObjectExtendsInnerAndReferencesOuterMember() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/objectExtendsInnerAndReferencesOuterMember.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 2620fb623ba..c26d042e53c 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -11993,6 +11993,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("classCompanion.kt") + public void testClassCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/classCompanion.kt"); + doTest(fileName); + } + @TestMetadata("flist.kt") public void testFlist() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt"); @@ -12011,6 +12017,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("interfaceCompanion.kt") + public void testInterfaceCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/interfaceCompanion.kt"); + doTest(fileName); + } + @TestMetadata("kt1047.kt") public void testKt1047() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/kt1047.kt"); @@ -12149,6 +12161,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes doTest(fileName); } + @TestMetadata("object.kt") + public void testObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/object.kt"); + doTest(fileName); + } + @TestMetadata("objectExtendsInnerAndReferencesOuterMember.kt") public void testObjectExtendsInnerAndReferencesOuterMember() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/objectExtendsInnerAndReferencesOuterMember.kt"); 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 ab3913eff31..0d2b6746927 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 @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.util.capitalizeDecapitalize.CapitalizeDecapitalizeKt import static org.jetbrains.kotlin.resolve.DescriptorUtils.isClassOrEnumClass; import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject; +import static org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface; public final class JvmAbi { public static final String DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls"; @@ -54,6 +55,7 @@ public final class JvmAbi { private static final String ANNOTATED_TYPEALIAS_METHOD_NAME_SUFFIX = ANNOTATIONS_SUFFIX; public static final String INSTANCE_FIELD = "INSTANCE"; + public static final String HIDDEN_INSTANCE_FIELD = "$$" + INSTANCE_FIELD; public static final String DEFAULT_MODULE_NAME = "main"; public static final ClassId REFLECTION_FACTORY_IMPL = ClassId.topLevel(new FqName("kotlin.reflect.jvm.internal.ReflectionFactoryImpl")); @@ -110,6 +112,16 @@ public final class JvmAbi { public static boolean isCompanionObjectWithBackingFieldsInOuter(@NotNull DeclarationDescriptor companionObject) { return isCompanionObject(companionObject) && isClassOrEnumClass(companionObject.getContainingDeclaration()) && - !CompanionObjectMapping.INSTANCE.isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject); + !isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject); + } + + public static boolean isMappedIntrinsicCompanionObject(@NotNull ClassDescriptor companionObject) { + return CompanionObjectMapping.INSTANCE.isMappedIntrinsicCompanionObject(companionObject); + } + + public static boolean isCompanionObjectInInterfaceNotIntrinsic(@NotNull DeclarationDescriptor companionObject) { + return isCompanionObject(companionObject) && + isInterface(companionObject.getContainingDeclaration()) && + !isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject); } } diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 9ac66809cee..03ff4053da0 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -13163,6 +13163,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("classCompanion.kt") + public void testClassCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/classCompanion.kt"); + doTest(fileName); + } + @TestMetadata("flist.kt") public void testFlist() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/flist.kt"); @@ -13181,6 +13187,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("interfaceCompanion.kt") + public void testInterfaceCompanion() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/interfaceCompanion.kt"); + doTest(fileName); + } + @TestMetadata("kt1047.kt") public void testKt1047() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/kt1047.kt"); @@ -13349,6 +13361,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { doTest(fileName); } + @TestMetadata("object.kt") + public void testObject() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/object.kt"); + doTest(fileName); + } + @TestMetadata("objectExtendsInnerAndReferencesOuterMember.kt") public void testObjectExtendsInnerAndReferencesOuterMember() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/objects/objectExtendsInnerAndReferencesOuterMember.kt");