From 1342743001dc5d8d56f4e17ea42bae26b55f3667 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Mon, 5 Dec 2016 12:04:10 +0300 Subject: [PATCH] Add KotlinVersion.IS_PRE_RELEASE and a flag to kotlin/Metadata --- .../kotlin/codegen/ClosureCodegen.java | 2 +- .../kotlin/codegen/MemberCodegen.java | 3 +- .../kotlin/codegen/MultifileClassCodegen.kt | 8 ++--- .../codegen/MultifileClassPartCodegen.kt | 8 ++--- .../kotlin/codegen/PackagePartCodegen.java | 2 +- .../kotlin/codegen/writeAnnotationUtil.kt | 9 ++++-- .../kotlin/load/java/JvmAnnotationNames.java | 5 +++- .../load/kotlin/header/KotlinClassHeader.kt | 29 ++++++++++--------- core/runtime.jvm/src/kotlin/Metadata.kt | 5 +++- .../kotlin/config/KotlinCompilerVersion.java | 14 +++++++++ 10 files changed, 54 insertions(+), 31 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java index 7c9f75f620d..3405ff4d21c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/ClosureCodegen.java @@ -241,7 +241,7 @@ public class ClosureCodegen extends MemberCodegen { final ProtoBuf.Function functionProto = serializer.functionProto(freeLambdaDescriptor).build(); - WriteAnnotationUtilKt.writeKotlinMetadata(v, KotlinClassHeader.Kind.SYNTHETIC_CLASS, new Function1() { + WriteAnnotationUtilKt.writeKotlinMetadata(v, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0, new Function1() { @Override public Unit invoke(AnnotationVisitor av) { writeAnnotationData(av, serializer, functionProto); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java index 6eb1d42ad8e..42fc4b4d3a6 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MemberCodegen.java @@ -756,7 +756,7 @@ public abstract class MemberCodegen() { + WriteAnnotationUtilKt.writeKotlinMetadata(v, KotlinClassHeader.Kind.CLASS, 0, new Function1() { @Override public Unit invoke(AnnotationVisitor av) { writeAnnotationData(av, serializer, classProto); @@ -764,5 +764,4 @@ public abstract class MemberCodegen + val extraFlags = if (shouldGeneratePartHierarchy) JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG else 0 + + writeKotlinMetadata(classBuilder, KotlinClassHeader.Kind.MULTIFILE_CLASS, extraFlags) { av -> val arv = av.visitArray(JvmAnnotationNames.METADATA_DATA_FIELD_NAME) for (internalName in partInternalNamesSorted) { arv.visit(null, internalName) } arv.visitEnd() - val multifileClassKind = if (shouldGeneratePartHierarchy) INHERITING else DELEGATING - av.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_KIND_FIELD_NAME, multifileClassKind.id) } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt index a8b5cf16aea..cfb7e3ac557 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/MultifileClassPartCodegen.kt @@ -24,8 +24,6 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader -import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.MultifileClassKind.DELEGATING -import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.MultifileClassKind.INHERITING import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtProperty @@ -180,11 +178,11 @@ class MultifileClassPartCodegen( val serializer = DescriptorSerializer.createTopLevel(JvmSerializerExtension(v.serializationBindings, state)) val packageProto = serializer.packagePartProto(members).build() - writeKotlinMetadata(v, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART) { av -> + val extraFlags = if (shouldGeneratePartHierarchy) JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG else 0 + + writeKotlinMetadata(v, KotlinClassHeader.Kind.MULTIFILE_CLASS_PART, extraFlags) { av -> AsmUtil.writeAnnotationData(av, serializer, packageProto) av.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME, facadeClassType.internalName) - val multifileClassKind = if (shouldGeneratePartHierarchy) INHERITING else DELEGATING - av.visit(JvmAnnotationNames.METADATA_MULTIFILE_CLASS_KIND_FIELD_NAME, multifileClassKind.id) } } diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java index 2635c13509e..977553e675f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java @@ -131,7 +131,7 @@ public class PackagePartCodegen extends MemberCodegen { DescriptorSerializer.createTopLevel(new JvmSerializerExtension(v.getSerializationBindings(), state)); final ProtoBuf.Package packageProto = serializer.packagePartProto(members).build(); - WriteAnnotationUtilKt.writeKotlinMetadata(v, KotlinClassHeader.Kind.FILE_FACADE, new Function1() { + WriteAnnotationUtilKt.writeKotlinMetadata(v, KotlinClassHeader.Kind.FILE_FACADE, 0, new Function1() { @Override public Unit invoke(AnnotationVisitor av) { writeAnnotationData(av, serializer, packageProto); diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/writeAnnotationUtil.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/writeAnnotationUtil.kt index e27fd85077e..d9c485cfd9c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/writeAnnotationUtil.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/writeAnnotationUtil.kt @@ -16,23 +16,28 @@ package org.jetbrains.kotlin.codegen +import org.jetbrains.kotlin.config.KotlinCompilerVersion import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader import org.jetbrains.org.objectweb.asm.AnnotationVisitor -fun writeKotlinMetadata(cb: ClassBuilder, kind: KotlinClassHeader.Kind, action: (AnnotationVisitor) -> Unit) { +fun writeKotlinMetadata(cb: ClassBuilder, kind: KotlinClassHeader.Kind, extraFlags: Int, action: (AnnotationVisitor) -> Unit) { val av = cb.newAnnotation(JvmAnnotationNames.METADATA_DESC, true) av.visit(JvmAnnotationNames.METADATA_VERSION_FIELD_NAME, JvmMetadataVersion.INSTANCE.toArray()) av.visit(JvmAnnotationNames.BYTECODE_VERSION_FIELD_NAME, JvmBytecodeBinaryVersion.INSTANCE.toArray()) av.visit(JvmAnnotationNames.KIND_FIELD_NAME, kind.id) + val flags = extraFlags or (if (KotlinCompilerVersion.IS_PRE_RELEASE) JvmAnnotationNames.METADATA_PRE_RELEASE_FLAG else 0) + if (flags != 0) { + av.visit(JvmAnnotationNames.METADATA_EXTRA_INT_FIELD_NAME, flags) + } action(av) av.visitEnd() } fun writeSyntheticClassMetadata(cb: ClassBuilder) { - writeKotlinMetadata(cb, KotlinClassHeader.Kind.SYNTHETIC_CLASS) { av -> + writeKotlinMetadata(cb, KotlinClassHeader.Kind.SYNTHETIC_CLASS, 0) { _ -> // Do nothing } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java index c07b6483b3c..6b98fd33b0b 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/JvmAnnotationNames.java @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.Name; import org.jetbrains.kotlin.resolve.jvm.JvmClassName; +@SuppressWarnings("PointlessBitwiseExpression") public final class JvmAnnotationNames { public static final FqName METADATA_FQ_NAME = new FqName("kotlin.Metadata"); public static final String METADATA_DESC = "L" + JvmClassName.byFqNameWithoutInnerClasses(METADATA_FQ_NAME).getInternalName() + ";"; @@ -32,7 +33,9 @@ public final class JvmAnnotationNames { public static final String METADATA_EXTRA_STRING_FIELD_NAME = "xs"; public static final String METADATA_MULTIFILE_CLASS_NAME_FIELD_NAME = METADATA_EXTRA_STRING_FIELD_NAME; public static final String METADATA_EXTRA_INT_FIELD_NAME = "xi"; - public static final String METADATA_MULTIFILE_CLASS_KIND_FIELD_NAME = METADATA_EXTRA_INT_FIELD_NAME; + + public static final int METADATA_MULTIFILE_PARTS_INHERIT_FLAG = 1 << 0; + public static final int METADATA_PRE_RELEASE_FLAG = 1 << 1; public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt index e2366fb5bca..549599d757e 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/kotlin/header/KotlinClassHeader.kt @@ -16,8 +16,11 @@ package org.jetbrains.kotlin.load.kotlin.header +import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmBytecodeBinaryVersion import org.jetbrains.kotlin.load.kotlin.JvmMetadataVersion +import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.MultifileClassKind.DELEGATING +import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader.MultifileClassKind.INHERITING class KotlinClassHeader( val kind: KotlinClassHeader.Kind, @@ -45,27 +48,27 @@ class KotlinClassHeader( } } - // See kotlin.Metadata - enum class MultifileClassKind(val id: Int) { - DELEGATING(0), - INHERITING(1); - - companion object { - private val entryById = values().associateBy(MultifileClassKind::id) - - @JvmStatic - fun getById(id: Int) = entryById[id] - } + enum class MultifileClassKind { + DELEGATING, + INHERITING; } val multifileClassName: String? get() = if (kind == Kind.MULTIFILE_CLASS_PART) extraString else null + // TODO: use in incremental compilation val multifileClassKind: MultifileClassKind? - get() = if (kind == Kind.MULTIFILE_CLASS || kind == Kind.MULTIFILE_CLASS_PART) - MultifileClassKind.getById(extraInt) + get() = if (kind == Kind.MULTIFILE_CLASS || kind == Kind.MULTIFILE_CLASS_PART) { + if ((extraInt and JvmAnnotationNames.METADATA_MULTIFILE_PARTS_INHERIT_FLAG) != 0) + INHERITING + else + DELEGATING + } else null + val isPreRelease: Boolean + get() = (extraInt and JvmAnnotationNames.METADATA_PRE_RELEASE_FLAG) != 0 + override fun toString() = "$kind version=$metadataVersion" } diff --git a/core/runtime.jvm/src/kotlin/Metadata.kt b/core/runtime.jvm/src/kotlin/Metadata.kt index d4868d718c9..d36ff113ce8 100644 --- a/core/runtime.jvm/src/kotlin/Metadata.kt +++ b/core/runtime.jvm/src/kotlin/Metadata.kt @@ -57,7 +57,10 @@ internal annotation class Metadata( */ val xs: String = "", /** - * An extra int. For multi-file class, represents code generation scheme. + * An extra int. Bits of this number represent the following flags: + * + * 0 - this is a multi-file class facade or part, compiled with `-Xmultifile-parts-inherit`. + * 1 - this class file is compiled by a pre-release version of Kotlin and is not visible to release versions. */ val xi: Int = 0 ) diff --git a/core/util.runtime/src/org/jetbrains/kotlin/config/KotlinCompilerVersion.java b/core/util.runtime/src/org/jetbrains/kotlin/config/KotlinCompilerVersion.java index 3ccef057196..42b47022b9d 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/config/KotlinCompilerVersion.java +++ b/core/util.runtime/src/org/jetbrains/kotlin/config/KotlinCompilerVersion.java @@ -20,4 +20,18 @@ public class KotlinCompilerVersion { // The value of this constant is generated by the build script // DON'T MODIFY IT public static final String VERSION = "@snapshot@"; + + // True if this compiler is of a non-stable (EAP or Beta) version. + // Binaries produced by this compiler can not be loaded by release versions of the compiler. + // Change this value before and after every major release + public static final boolean IS_PRE_RELEASE = true; + + static { + if (!VERSION.equals("@snapshot@") && !VERSION.contains("-") && IS_PRE_RELEASE) { + throw new IllegalStateException( + "IS_PRE_RELEASE cannot be false for a compiler without '-' in its version.\n" + + "Please change IS_PRE_RELEASE to false, commit and push this change to master" + ); + } + } }