Use internal names in multifile class metadata

To reuse the strings already existing in the constant pool of the class file
This commit is contained in:
Alexander Udalov
2015-10-01 20:59:56 +03:00
parent e1ccb92438
commit bdd69d9e46
6 changed files with 14 additions and 35 deletions
@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.codegen.context.MethodContext
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.config.IncrementalCompilation import org.jetbrains.kotlin.config.IncrementalCompilation
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil import org.jetbrains.kotlin.fileClasses.JvmFileClassUtil
@@ -57,7 +56,6 @@ import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
import java.util.* import java.util.*
public class MultifileClassCodegen( public class MultifileClassCodegen(
private val state: GenerationState, private val state: GenerationState,
public val files: Collection<JetFile>, public val files: Collection<JetFile>,
@@ -200,7 +198,7 @@ public class MultifileClassCodegen(
val builder = state.factory.newVisitor(MultifileClassPart(file, packageFragment, facadeFqName), partType, file) val builder = state.factory.newVisitor(MultifileClassPart(file, packageFragment, facadeFqName), partType, file)
MultifileClassPartCodegen(builder, file, partType, facadeFqName, partContext, state).generate() MultifileClassPartCodegen(builder, file, partType, facadeClassType, partContext, state).generate()
val facadeContext = state.rootContext.intoMultifileClass(packageFragment, facadeClassType, partType) val facadeContext = state.rootContext.intoMultifileClass(packageFragment, facadeClassType, partType)
val memberCodegen = createCodegenForPartOfMultifileFacade(facadeContext) val memberCodegen = createCodegenForPartOfMultifileFacade(facadeContext)
@@ -280,12 +278,12 @@ public class MultifileClassCodegen(
val av = classBuilder.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS), true) val av = classBuilder.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS), true)
JvmCodegenUtil.writeAbiVersion(av) JvmCodegenUtil.writeAbiVersion(av)
val shortNames = partFqNames.map { it.shortName().asString() }.sorted() val partInternalNames = partFqNames.map { JvmClassName.byFqNameWithoutInnerClasses(it).internalName }.sorted()
val filePartClassNamesArray = av.visitArray(JvmAnnotationNames.FILE_PART_CLASS_NAMES_FIELD_NAME) val arv = av.visitArray(JvmAnnotationNames.FILE_PART_CLASS_NAMES_FIELD_NAME)
for (shortName in shortNames) { for (internalName in partInternalNames) {
filePartClassNamesArray.visit(null, shortName) arv.visit(null, internalName)
} }
filePartClassNamesArray.visitEnd() arv.visitEnd()
av.visitEnd() av.visitEnd()
} }
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.codegen.serialization.JvmSerializerExtension
import org.jetbrains.kotlin.codegen.state.GenerationState import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.load.java.JvmAnnotationNames import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.JetFile import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.psi.JetNamedFunction import org.jetbrains.kotlin.psi.JetNamedFunction
import org.jetbrains.kotlin.psi.JetProperty import org.jetbrains.kotlin.psi.JetProperty
@@ -36,7 +35,7 @@ public class MultifileClassPartCodegen(
v: ClassBuilder, v: ClassBuilder,
file: JetFile, file: JetFile,
private val filePartType: Type, private val filePartType: Type,
private val multifileClassFqName: FqName, private val multifileClassType: Type,
partContext: FieldOwnerContext<*>, partContext: FieldOwnerContext<*>,
state: GenerationState state: GenerationState
) : MemberCodegen<JetFile>(state, null, partContext, file, v) { ) : MemberCodegen<JetFile>(state, null, partContext, file, v) {
@@ -97,7 +96,7 @@ public class MultifileClassPartCodegen(
val av = v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS_PART), true) val av = v.newAnnotation(AsmUtil.asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_MULTIFILE_CLASS_PART), true)
AsmUtil.writeAnnotationData(av, serializer, packageProto) AsmUtil.writeAnnotationData(av, serializer, packageProto)
av.visit(JvmAnnotationNames.MULTIFILE_CLASS_NAME_FIELD_NAME, multifileClassFqName.shortName().asString()) av.visit(JvmAnnotationNames.MULTIFILE_CLASS_NAME_FIELD_NAME, multifileClassType.internalName)
av.visitEnd() av.visitEnd()
} }
} }
@@ -61,7 +61,7 @@ public class LazyJavaPackageScope(
KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> { KotlinClassHeader.Kind.MULTIFILE_CLASS_PART -> {
val partName = kotlinClass.classId.shortClassName.asString() val partName = kotlinClass.classId.shortClassName.asString()
val facadeName = header.multifileClassName ?: continue@kotlinClasses val facadeName = header.multifileClassName ?: continue@kotlinClasses
result[partName] = facadeName result[partName] = facadeName.substringAfterLast('/')
} }
KotlinClassHeader.Kind.FILE_FACADE -> { KotlinClassHeader.Kind.FILE_FACADE -> {
val fileFacadeName = kotlinClass.classId.shortClassName.asString() val fileFacadeName = kotlinClass.classId.shortClassName.asString()
@@ -89,9 +89,6 @@ public fun findMultifileClassParts(file: VirtualFile, multifileClass: KotlinJvmB
val partsFinder = DirectoryBasedClassFinder(file.parent!!, packageFqName) val partsFinder = DirectoryBasedClassFinder(file.parent!!, packageFqName)
val partNames = multifileClass.classHeader.filePartClassNames ?: return emptyList() val partNames = multifileClass.classHeader.filePartClassNames ?: return emptyList()
return partNames.map { return partNames.map {
partsFinder.findKotlinClass(ClassId(packageFqName, Name.identifier(it))) partsFinder.findKotlinClass(ClassId(packageFqName, Name.identifier(it.substringAfterLast('/'))))
}.filterNotNull() }.filterNotNull()
} }
public fun readMultifileClassPartHeaders(file: VirtualFile, multifileClass: KotlinJvmBinaryClass): List<KotlinClassHeader> =
findMultifileClassParts(file, multifileClass).map { it.classHeader }
@@ -80,7 +80,7 @@ fun createMultifileClassStub(
components: ClsStubBuilderComponents components: ClsStubBuilderComponents
): KotlinFileStubImpl { ): KotlinFileStubImpl {
val packageFqName = facadeFqName.parent() val packageFqName = facadeFqName.parent()
val partNames = multifileClass.classHeader.filePartClassNames?.asList() val partNames = multifileClass.classHeader.filePartClassNames?.asList()?.map { it.substringAfterLast('/') }
val fileStub = KotlinFileStubForIde.forMultifileClassStub(facadeFqName, partNames, packageFqName.isRoot) val fileStub = KotlinFileStubForIde.forMultifileClassStub(facadeFqName, partNames, packageFqName.isRoot)
setupFileStub(fileStub, packageFqName) setupFileStub(fileStub, packageFqName)
for (partFile in partFiles) { for (partFile in partFiles) {
@@ -198,7 +198,8 @@ public class IncrementalCacheImpl(
inlineFunctionsMap.process(kotlinClass) inlineFunctionsMap.process(kotlinClass)
} }
header.isCompatibleMultifileClassKind() -> { header.isCompatibleMultifileClassKind() -> {
val partNames = getFullNamesOfMultifileClassParts(kotlinClass) val partNames = kotlinClass.classHeader.filePartClassNames?.toList()
?: throw AssertionError("Multifile class has no parts: ${kotlinClass.className}")
multifileClassFacadeMap.add(className, partNames) multifileClassFacadeMap.add(className, partNames)
// TODO NO_CHANGES? (delegates only, see package facade) // TODO NO_CHANGES? (delegates only, see package facade)
@@ -208,8 +209,7 @@ public class IncrementalCacheImpl(
header.isCompatibleMultifileClassPartKind() -> { header.isCompatibleMultifileClassPartKind() -> {
assert(sourceFiles.size() == 1) { "Multifile class part from several source files: $sourceFiles" } assert(sourceFiles.size() == 1) { "Multifile class part from several source files: $sourceFiles" }
packagePartMap.addPackagePart(className) packagePartMap.addPackagePart(className)
val facadeClassName = getInternalNameOfTopLevelClassInTheSamePackage(kotlinClass, header.multifileClassName!!) multifileClassPartMap.add(className.internalName, header.multifileClassName!!)
multifileClassPartMap.add(className.internalName, facadeClassName)
protoMap.process(kotlinClass, isPackage = true) + protoMap.process(kotlinClass, isPackage = true) +
constantsMap.process(kotlinClass) + constantsMap.process(kotlinClass) +
@@ -698,21 +698,6 @@ private fun ByteArray.md5(): Long {
) )
} }
private fun getInternalNameOfTopLevelClassInTheSamePackage(kotlinClass: KotlinJvmBinaryClass, simpleName: String): String {
val classFqName = kotlinClass.classId.packageFqName.child(Name.identifier(simpleName))
return JvmClassName.byFqNameWithoutInnerClasses(classFqName).internalName
}
private fun getFullNamesOfMultifileClassParts(kotlinClass: LocalFileKotlinClass): List<String> {
val classHeader = kotlinClass.classHeader
val partClassNames = classHeader.filePartClassNames ?: throw AssertionError("Multifile class has no parts: ${kotlinClass.className}")
val fullNames = arrayListOf<String>()
for (shortName in partClassNames) {
fullNames.add(getInternalNameOfTopLevelClassInTheSamePackage(kotlinClass, shortName))
}
return fullNames
}
private abstract class StringMapExternalizer<T> : DataExternalizer<Map<String, T>> { private abstract class StringMapExternalizer<T> : DataExternalizer<Map<String, T>> {
override fun save(out: DataOutput, map: Map<String, T>?) { override fun save(out: DataOutput, map: Map<String, T>?) {
out.writeInt(map!!.size()) out.writeInt(map!!.size())