From 1ce5f8458c7a1bcd195dc56b69c187cb274b71ef Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 21 Oct 2015 14:53:07 +0300 Subject: [PATCH] Extract ClassMapperLite, add enlightening comment --- .../serialization/JvmSerializerExtension.java | 4 +- .../serialization/jvm/ClassMapperLite.kt | 52 +++++++++++++++++++ .../serialization/jvm/JvmProtoBufUtil.kt | 28 +--------- 3 files changed, 55 insertions(+), 29 deletions(-) create mode 100644 core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/ClassMapperLite.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.java index 1efe2328e7a..4d255d23177 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/serialization/JvmSerializerExtension.java @@ -29,8 +29,8 @@ import org.jetbrains.kotlin.serialization.AnnotationSerializer; import org.jetbrains.kotlin.serialization.ProtoBuf; import org.jetbrains.kotlin.serialization.SerializerExtension; import org.jetbrains.kotlin.serialization.StringTable; +import org.jetbrains.kotlin.serialization.jvm.ClassMapperLite; import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf; -import org.jetbrains.kotlin.serialization.jvm.JvmProtoBufUtil; import org.jetbrains.kotlin.types.KotlinType; import org.jetbrains.org.objectweb.asm.Type; import org.jetbrains.org.objectweb.asm.commons.Method; @@ -217,7 +217,7 @@ public class JvmSerializerExtension extends SerializerExtension { ClassifierDescriptor classifier = type.getConstructor().getDeclarationDescriptor(); if (!(classifier instanceof ClassDescriptor)) return null; ClassId classId = classId((ClassDescriptor) classifier); - return classId == null ? null : JvmProtoBufUtil.mapClassIdDefault(classId); + return classId == null ? null : ClassMapperLite.mapClass(classId); } @Nullable diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/ClassMapperLite.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/ClassMapperLite.kt new file mode 100644 index 00000000000..300868dd3ad --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/ClassMapperLite.kt @@ -0,0 +1,52 @@ +/* + * 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.jvm + +import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.platform.JavaToKotlinClassMap +import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType + +// The purpose of this class is to map Kotlin classes to JVM bytecode desc strings, as JetTypeMapper does in the backend. +// It's used as an optimization during serialization/deserialization: if there's no JVM signature for a method/property/constructor, +// it means that the JVM signature should be trivially computable from the Kotlin signature with this class. +// It's not required to support everything in JetTypeMapper, but the more it does, the more we save on JVM signatures in proto metadata. +// Note that improving the behavior of this class may break binary compatibility of code compiled by Kotlin, because it may make +// the new compiler skip writing the signatures it now thinks are trivial, and the old compiler would recreate them incorrectly. +object ClassMapperLite { + @JvmStatic + fun mapClass(classId: ClassId): String { + val internalName = classId.asString().replace('.', '$') + val simpleName = internalName.removePrefix("kotlin/") + if (simpleName != internalName) { + for (jvmPrimitive in JvmPrimitiveType.values) { + val primitiveType = jvmPrimitive.primitiveType + if (simpleName == primitiveType.typeName.asString()) return jvmPrimitive.desc + if (simpleName == primitiveType.arrayTypeName.asString()) return "[" + jvmPrimitive.desc + } + + if (simpleName == KotlinBuiltIns.FQ_NAMES.unit.shortName().asString()) return "V" + } + + val javaClassId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(classId.asSingleFqName().toUnsafe()) + if (javaClassId != null) { + return "L" + javaClassId.asString().replace('.', '$') + ";" + } + + return "L$internalName;" + } +} diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/JvmProtoBufUtil.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/JvmProtoBufUtil.kt index 1658fdab8a4..bedfe0cc564 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/JvmProtoBufUtil.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/serialization/jvm/JvmProtoBufUtil.kt @@ -17,11 +17,7 @@ package org.jetbrains.kotlin.serialization.jvm import com.google.protobuf.ExtensionRegistryLite -import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.load.kotlin.JvmNameResolver -import org.jetbrains.kotlin.name.ClassId -import org.jetbrains.kotlin.platform.JavaToKotlinClassMap -import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType import org.jetbrains.kotlin.serialization.ClassData import org.jetbrains.kotlin.serialization.PackageData import org.jetbrains.kotlin.serialization.ProtoBuf @@ -122,28 +118,6 @@ public object JvmProtoBufUtil { data class PropertySignature(val name: String, val desc: String) private fun mapTypeDefault(type: ProtoBuf.Type, nameResolver: NameResolver): String? { - return if (type.hasClassName()) mapClassIdDefault(nameResolver.getClassId(type.className)) else null - } - - @JvmStatic - fun mapClassIdDefault(classId: ClassId): String { - val internalName = classId.asString().replace('.', '$') - val simpleName = internalName.removePrefix("kotlin/") - if (simpleName != internalName) { - for (jvmPrimitive in JvmPrimitiveType.values()) { - val primitiveType = jvmPrimitive.primitiveType - if (simpleName == primitiveType.typeName.asString()) return jvmPrimitive.desc - if (simpleName == primitiveType.arrayTypeName.asString()) return "[" + jvmPrimitive.desc - } - - if (simpleName == KotlinBuiltIns.FQ_NAMES.unit.shortName().asString()) return "V" - } - - val javaClassId = JavaToKotlinClassMap.INSTANCE.mapKotlinToJava(classId.asSingleFqName().toUnsafe()) - if (javaClassId != null) { - return "L" + javaClassId.asString().replace('.', '$') + ";" - } - - return "L$internalName;" + return if (type.hasClassName()) ClassMapperLite.mapClass(nameResolver.getClassId(type.className)) else null } }