From 5c1adb1258b4fbbc2a2e082d0c0343e56012ca93 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 14 Dec 2016 16:07:51 +0300 Subject: [PATCH] Serialize SinceKotlinInfo and SinceKotlinInfoTable --- .../serialization/DescriptorSerializer.kt | 21 +++++- .../kotlin/serialization/MutableTable.kt | 72 +++++++++++++++++++ .../kotlin/serialization/MutableTypeTable.kt | 45 ------------ .../descriptors/SinceKotlinInfo.kt | 14 +++- 4 files changed, 103 insertions(+), 49 deletions(-) create mode 100644 compiler/serialization/src/org/jetbrains/kotlin/serialization/MutableTable.kt delete mode 100644 compiler/serialization/src/org/jetbrains/kotlin/serialization/MutableTypeTable.kt diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt index f01a973e180..4c79bded823 100644 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/DescriptorSerializer.kt @@ -35,6 +35,7 @@ class DescriptorSerializer private constructor( private val typeParameters: Interner, private val extension: SerializerExtension, private val typeTable: MutableTypeTable, + private val sinceKotlinInfoTable: MutableSinceKotlinInfoTable, private val serializeTypeTableToFunction: Boolean ) { fun serialize(message: MessageLite): ByteArray { @@ -45,7 +46,8 @@ class DescriptorSerializer private constructor( } private fun createChildSerializer(descriptor: DeclarationDescriptor): DescriptorSerializer = - DescriptorSerializer(descriptor, Interner(typeParameters), extension, typeTable, serializeTypeTableToFunction = false) + DescriptorSerializer(descriptor, Interner(typeParameters), extension, typeTable, sinceKotlinInfoTable, + serializeTypeTableToFunction = false) val stringTable: StringTable get() = extension.stringTable @@ -121,6 +123,11 @@ class DescriptorSerializer private constructor( builder.typeTable = typeTableProto } + val sinceKotlinInfoProto = sinceKotlinInfoTable.serialize() + if (sinceKotlinInfoProto != null) { + builder.sinceKotlinInfoTable = sinceKotlinInfoProto + } + extension.serializeClass(classDescriptor, builder) return builder @@ -511,6 +518,11 @@ class DescriptorSerializer private constructor( builder.typeTable = typeTableProto } + val sinceKotlinInfoProto = sinceKotlinInfoTable.serialize() + if (sinceKotlinInfoProto != null) { + builder.sinceKotlinInfoTable = sinceKotlinInfoProto + } + extension.serializePackage(builder) return builder @@ -528,12 +540,14 @@ class DescriptorSerializer private constructor( companion object { @JvmStatic fun createTopLevel(extension: SerializerExtension): DescriptorSerializer { - return DescriptorSerializer(null, Interner(), extension, MutableTypeTable(), serializeTypeTableToFunction = false) + return DescriptorSerializer(null, Interner(), extension, MutableTypeTable(), MutableSinceKotlinInfoTable(), + serializeTypeTableToFunction = false) } @JvmStatic fun createForLambda(extension: SerializerExtension): DescriptorSerializer { - return DescriptorSerializer(null, Interner(), extension, MutableTypeTable(), serializeTypeTableToFunction = true) + return DescriptorSerializer(null, Interner(), extension, MutableTypeTable(), MutableSinceKotlinInfoTable(), + serializeTypeTableToFunction = true) } @JvmStatic @@ -552,6 +566,7 @@ class DescriptorSerializer private constructor( Interner(parentSerializer.typeParameters), parentSerializer.extension, MutableTypeTable(), + MutableSinceKotlinInfoTable(), serializeTypeTableToFunction = false ) for (typeParameter in descriptor.declaredTypeParameters) { diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/MutableTable.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/MutableTable.kt new file mode 100644 index 00000000000..76e986a702e --- /dev/null +++ b/compiler/serialization/src/org/jetbrains/kotlin/serialization/MutableTable.kt @@ -0,0 +1,72 @@ +/* + * 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. + */ + +@file:Suppress("FINITE_BOUNDS_VIOLATION_IN_JAVA") +package org.jetbrains.kotlin.serialization + +import org.jetbrains.kotlin.protobuf.GeneratedMessageLite +import org.jetbrains.kotlin.utils.Interner +import java.util.* + +private class TableElementWrapper>(val builder: Element) { + // If you'll try to optimize it using structured equals/hashCode, pay attention to extensions present in proto messages + private val bytes: ByteArray = builder.build().toByteArray() + private val hashCode: Int = Arrays.hashCode(bytes) + + override fun hashCode() = hashCode + + override fun equals(other: Any?) = other is TableElementWrapper<*> && Arrays.equals(bytes, other.bytes) +} + +abstract class MutableTable + where Element : GeneratedMessageLite.Builder<*, Element>, + Table : GeneratedMessageLite, + TableBuilder : GeneratedMessageLite.Builder { + + private val interner = Interner>() + + protected abstract fun createTableBuilder(): TableBuilder + + protected abstract fun addElement(builder: TableBuilder, element: Element) + + operator fun get(type: Element): Int = + interner.intern(TableElementWrapper(type)) + + @Suppress("UNCHECKED_CAST") + fun serialize(): Table? = + if (interner.isEmpty) null + else createTableBuilder().apply { + for (obj in interner.allInternedObjects) { + addElement(this, obj.builder) + } + }.build() as Table +} + +class MutableTypeTable : MutableTable() { + override fun createTableBuilder(): ProtoBuf.TypeTable.Builder = ProtoBuf.TypeTable.newBuilder() + + override fun addElement(builder: ProtoBuf.TypeTable.Builder, element: ProtoBuf.Type.Builder) { + builder.addType(element) + } +} + +class MutableSinceKotlinInfoTable : MutableTable() { + override fun createTableBuilder(): ProtoBuf.SinceKotlinInfoTable.Builder = ProtoBuf.SinceKotlinInfoTable.newBuilder() + + override fun addElement(builder: ProtoBuf.SinceKotlinInfoTable.Builder, element: ProtoBuf.SinceKotlinInfo.Builder) { + builder.addInfo(element) + } +} diff --git a/compiler/serialization/src/org/jetbrains/kotlin/serialization/MutableTypeTable.kt b/compiler/serialization/src/org/jetbrains/kotlin/serialization/MutableTypeTable.kt deleted file mode 100644 index 637960dfb33..00000000000 --- a/compiler/serialization/src/org/jetbrains/kotlin/serialization/MutableTypeTable.kt +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2010-2015 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.serialization - -import org.jetbrains.kotlin.utils.Interner -import java.util.* - -class MutableTypeTable { - class TypeWrapper(val type: ProtoBuf.Type.Builder) { - // If you'll try to optimize it using structured equals/hashCode, pay attention to extensions present in Type messages - private val bytes: ByteArray = type.build().toByteArray() - private val hashCode: Int = Arrays.hashCode(bytes) - - override fun hashCode() = hashCode - - override fun equals(other: Any?) = other is TypeWrapper && Arrays.equals(bytes, other.bytes) - } - - val interner = Interner() - - operator fun get(type: ProtoBuf.Type.Builder): Int = - interner.intern(TypeWrapper(type)) - - fun serialize(): ProtoBuf.TypeTable? = - if (interner.isEmpty) null - else ProtoBuf.TypeTable.newBuilder().apply { - for (type in interner.allInternedObjects) { - addType(type.type) - } - }.build() -} diff --git a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/SinceKotlinInfo.kt b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/SinceKotlinInfo.kt index 9e0314a1c1d..93b8c4435d7 100644 --- a/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/SinceKotlinInfo.kt +++ b/core/deserialization/src/org/jetbrains/kotlin/serialization/deserialization/descriptors/SinceKotlinInfo.kt @@ -37,10 +37,22 @@ class SinceKotlinInfo( val errorCode: Int?, val message: String? ) { - class Version(val major: Int, val minor: Int, val patch: Int) { + data class Version(val major: Int, val minor: Int, val patch: Int = 0) { fun asString(): String = if (patch == 0) "$major.$minor" else "$major.$minor.$patch" + fun encode( + writeVersion: (Int) -> Unit, + writeVersionFull: (Int) -> Unit + ) { + if (major > MAJOR_MASK || minor > MINOR_MASK || patch > PATCH_MASK) { + writeVersionFull(major or (minor shl 8) or (patch shl 16)) + } + else if (this != DEFAULT) { + writeVersion(major or (minor shl MAJOR_BITS) or (patch shl (MAJOR_BITS + MINOR_BITS))) + } + } + override fun toString(): String = asString() companion object {