From 17cf1df4f4953f8d6f3171b96c3ae88edac5610f Mon Sep 17 00:00:00 2001 From: Nikolay Igotti Date: Wed, 24 Oct 2018 11:40:54 +0300 Subject: [PATCH] Store source file info in klib. (#2243) --- .../konan/descriptors/DescriptorUtils.kt | 32 ++++++++++- .../konan/library/KonanLibraryWriter.kt | 2 +- .../objcexport/ObjCExportHeaderGenerator.kt | 2 +- .../serialization/KonanSerializationUtil.kt | 16 ++++-- .../serialization/KonanSerializerExtension.kt | 10 ++-- .../konan.metadata/src/KonanProtoBuf.proto | 3 + .../resolver/impl/KonanResolvedLibraryImpl.kt | 5 +- .../konan/KonanPackageFragment.kt | 22 ++++++++ .../serialization/konan/SourceFileMap.kt | 55 +++++++++++++++++++ 9 files changed, 132 insertions(+), 15 deletions(-) create mode 100644 extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/SourceFileMap.kt diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt index 9c186c70256..171f7f22528 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/DescriptorUtils.kt @@ -7,12 +7,21 @@ package org.jetbrains.kotlin.backend.konan.descriptors import org.jetbrains.kotlin.backend.konan.binaryTypeIsReference import org.jetbrains.kotlin.backend.konan.irasdescriptors.* +import org.jetbrains.kotlin.backend.konan.irasdescriptors.ClassDescriptor +import org.jetbrains.kotlin.backend.konan.irasdescriptors.ConstructorDescriptor +import org.jetbrains.kotlin.backend.konan.irasdescriptors.DeclarationDescriptor +import org.jetbrains.kotlin.backend.konan.irasdescriptors.FunctionDescriptor +import org.jetbrains.kotlin.backend.konan.irasdescriptors.PackageFragmentDescriptor +import org.jetbrains.kotlin.backend.konan.irasdescriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.backend.konan.isInlined -import org.jetbrains.kotlin.descriptors.ClassKind -import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.types.isUnit +import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedSimpleFunctionDescriptor +import org.jetbrains.kotlin.serialization.konan.KonanPackageFragment import org.jetbrains.kotlin.types.SimpleType /** @@ -231,3 +240,22 @@ tailrec internal fun DeclarationDescriptor.findPackage(): PackageFragmentDescrip fun FunctionDescriptor.isComparisonDescriptor(map: Map): Boolean = this in map.values + +private fun sourceByIndex(descriptor: CallableMemberDescriptor, index: Int): SourceFile { + val fragment = descriptor.findPackage() as KonanPackageFragment + return fragment.sourceFileMap.sourceFile(index) +} + +fun CallableMemberDescriptor.findSourceFile(): SourceFile { + val source = this.source.containingFile + if (source != SourceFile.NO_SOURCE_FILE) + return source + return when { + this is DeserializedSimpleFunctionDescriptor && proto.hasExtension(KonanProtoBuf.functionFile) -> sourceByIndex( + this, proto.getExtension(KonanProtoBuf.functionFile)) + this is DeserializedPropertyDescriptor && proto.hasExtension(KonanProtoBuf.propertyFile) -> + sourceByIndex( + this, proto.getExtension(KonanProtoBuf.propertyFile)) + else -> TODO() + } +} diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryWriter.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryWriter.kt index 6142e2f3735..a34fca1d539 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryWriter.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/library/KonanLibraryWriter.kt @@ -26,7 +26,7 @@ interface KonanLibraryWriter { class LinkData( val module: ByteArray, val fragments: List>, - val fragmentNames: List + val fragmentNames: List ) interface MetadataWriter { diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt index 497af70c9cc..25c3d1bd87d 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/objcexport/ObjCExportHeaderGenerator.kt @@ -193,7 +193,7 @@ abstract class ObjCExportHeaderGenerator( if (classDescriptor != null) { extensions.getOrPut(classDescriptor, { mutableListOf() }) += it } else { - topLevel.getOrPut(it.source.containingFile, { mutableListOf() }) += it + topLevel.getOrPut(it.findSourceFile(), { mutableListOf() }) += it } } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt index 84deaeb6127..33ab5493f7f 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializationUtil.kt @@ -13,14 +13,13 @@ import org.jetbrains.kotlin.metadata.ProtoBuf import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.DescriptorUtils -import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker import org.jetbrains.kotlin.resolve.descriptorUtil.module import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter.Companion.CALLABLES import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter.Companion.CLASSIFIERS import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer +import org.jetbrains.kotlin.serialization.konan.SourceFileMap /* * This is Konan specific part of public descriptor @@ -37,6 +36,8 @@ internal class KonanSerializationUtil(val context: Context, private val metadata lateinit var serializerContext: SerializerContext + val sourceFileMap = SourceFileMap() + data class SerializerContext( val serializerExtension: KonanSerializerExtension, val topSerializer: KonanDescriptorSerializer, @@ -44,7 +45,7 @@ internal class KonanSerializationUtil(val context: Context, private val metadata ) private fun createNewContext(): SerializerContext { - val extension = KonanSerializerExtension(context, metadataVersion) + val extension = KonanSerializerExtension(context, metadataVersion, sourceFileMap) return SerializerContext( extension, KonanDescriptorSerializer.createTopLevel(context, extension) @@ -213,7 +214,8 @@ internal class KonanSerializationUtil(val context: Context, private val metadata val fragmentNames = mutableListOf() getPackagesFqNames(moduleDescriptor).forEach iteration@{ packageFqName -> - val packageProtos = serializePackage(packageFqName, moduleDescriptor) + val packageProtos = + serializePackage(packageFqName, moduleDescriptor) if (packageProtos.isEmpty()) return@iteration val packageFqNameStr = packageFqName.asString() @@ -223,7 +225,13 @@ internal class KonanSerializationUtil(val context: Context, private val metadata } fragments.add(packageProtos.map { it.toByteArray() }) fragmentNames.add(packageFqNameStr) + } + + sourceFileMap.filesAndClear().map { it.name ?: "" }.forEach { + libraryProto.addFile(it) + } + val libraryAsByteArray = libraryProto.build().toByteArray() return LinkData(libraryAsByteArray, fragments, fragmentNames) } diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt index 464fe5cb8b0..5fcff1ff2e3 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/serialization/KonanSerializerExtension.kt @@ -16,9 +16,11 @@ import org.jetbrains.kotlin.metadata.serialization.MutableVersionRequirementTabl import org.jetbrains.kotlin.serialization.KonanDescriptorSerializer import org.jetbrains.kotlin.serialization.KotlinSerializerExtensionBase import org.jetbrains.kotlin.serialization.konan.KonanSerializerProtocol +import org.jetbrains.kotlin.serialization.konan.SourceFileMap import org.jetbrains.kotlin.types.KotlinType -internal class KonanSerializerExtension(val context: Context, override val metadataVersion: BinaryVersion) : +internal class KonanSerializerExtension(val context: Context, override val metadataVersion: BinaryVersion, + val sourceFileMap: SourceFileMap) : KotlinSerializerExtensionBase(KonanSerializerProtocol), IrAwareExtension { val inlineDescriptorTable = DescriptorTable(context.irBuiltIns) @@ -28,7 +30,7 @@ internal class KonanSerializerExtension(val context: Context, override val metad override fun serializeType(type: KotlinType, proto: ProtoBuf.Type.Builder) { // TODO: For debugging purpose we store the textual // representation of serialized types. - // To be removed for release 1.0. + // To be removed. proto.setExtension(KonanProtoBuf.typeText, type.toString()) super.serializeType(type, proto) @@ -60,7 +62,7 @@ internal class KonanSerializerExtension(val context: Context, override val metad } override fun serializeFunction(descriptor: FunctionDescriptor, proto: ProtoBuf.Function.Builder) { - + proto.setExtension(KonanProtoBuf.functionFile, sourceFileMap.assign(descriptor.source.containingFile)) super.serializeFunction(descriptor, proto) } @@ -69,7 +71,7 @@ internal class KonanSerializerExtension(val context: Context, override val metad if (variable != null) { proto.setExtension(KonanProtoBuf.usedAsVariable, true) } - + proto.setExtension(KonanProtoBuf.propertyFile, sourceFileMap.assign(descriptor.source.containingFile)) proto.setExtension(KonanProtoBuf.hasBackingField, context.ir.propertiesWithBackingFields.contains(descriptor)) diff --git a/extracted/konan.metadata/src/KonanProtoBuf.proto b/extracted/konan.metadata/src/KonanProtoBuf.proto index 63f18e8c139..86a9c05eb2b 100644 --- a/extracted/konan.metadata/src/KonanProtoBuf.proto +++ b/extracted/konan.metadata/src/KonanProtoBuf.proto @@ -32,6 +32,7 @@ extend Constructor { extend Function { repeated Annotation function_annotation = 170; optional InlineIrBody inline_ir_body = 171; + optional int32 function_file = 172; } extend Property { @@ -41,6 +42,7 @@ extend Property { optional Annotation.Argument.Value compile_time_value = 173; optional InlineIrBody inline_getter_ir_body = 174; optional InlineIrBody inline_setter_ir_body = 175; + optional int32 property_file = 176; } extend EnumEntry { @@ -95,5 +97,6 @@ message LinkDataLibrary { required string module_name = 1; repeated string package_fragment_name = 2; repeated string empty_package = 3; + repeated string file = 4; } diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/resolver/impl/KonanResolvedLibraryImpl.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/resolver/impl/KonanResolvedLibraryImpl.kt index 37c94d875f3..dc7f578f587 100644 --- a/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/resolver/impl/KonanResolvedLibraryImpl.kt +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/konan/library/resolver/impl/KonanResolvedLibraryImpl.kt @@ -2,11 +2,10 @@ package org.jetbrains.kotlin.konan.library.resolver.impl import org.jetbrains.kotlin.konan.library.KonanLibrary import org.jetbrains.kotlin.konan.library.resolver.KonanResolvedLibrary +import org.jetbrains.kotlin.serialization.konan.SourceFileMap import org.jetbrains.kotlin.serialization.konan.parseModuleHeader -internal class KonanResolvedLibraryImpl( - override val library: KonanLibrary -): KonanResolvedLibrary { +internal class KonanResolvedLibraryImpl(override val library: KonanLibrary): KonanResolvedLibrary { private val _resolvedDependencies = mutableListOf() private val _emptyPackages by lazy { parseModuleHeader(library.moduleHeaderData).emptyPackageList } diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanPackageFragment.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanPackageFragment.kt index 80f15b8746a..56766b9e375 100644 --- a/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanPackageFragment.kt +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/KonanPackageFragment.kt @@ -1,8 +1,15 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ package org.jetbrains.kotlin.serialization.konan import org.jetbrains.kotlin.descriptors.ModuleDescriptor +import org.jetbrains.kotlin.descriptors.SourceFile import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.konan.library.resolver.KonanResolvedLibrary import org.jetbrains.kotlin.konan.library.resolver.PackageAccessedHandler +import org.jetbrains.kotlin.konan.library.resolver.impl.KonanResolvedLibraryImpl import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl import org.jetbrains.kotlin.metadata.konan.KonanProtoBuf import org.jetbrains.kotlin.name.FqName @@ -14,6 +21,17 @@ import org.jetbrains.kotlin.serialization.deserialization.getClassId import org.jetbrains.kotlin.serialization.deserialization.getName import org.jetbrains.kotlin.storage.StorageManager + +private val KonanLibrary.fileSources: SourceFileMap get() { + val result = SourceFileMap() + val proto = parseModuleHeader(moduleHeaderData) + proto.fileList.forEachIndexed { index, it -> + result.provide(it, index, this) + } + return result +} + + class KonanPackageFragment( fqName: FqName, private val library: KonanLibrary, @@ -23,6 +41,10 @@ class KonanPackageFragment( partName: String ) : DeserializedPackageFragment(fqName, storageManager, module) { + val sourceFileMap: SourceFileMap by lazy { + library.fileSources + } + lateinit var components: DeserializationComponents override fun initialize(components: DeserializationComponents) { diff --git a/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/SourceFileMap.kt b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/SourceFileMap.kt new file mode 100644 index 00000000000..01f13a271ae --- /dev/null +++ b/extracted/konan.serializer/src/org/jetbrains/kotlin/serialization/konan/SourceFileMap.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the LICENSE file. + */ +package org.jetbrains.kotlin.serialization.konan + +import org.jetbrains.kotlin.descriptors.SourceFile +import org.jetbrains.kotlin.konan.library.KonanLibrary +import org.jetbrains.kotlin.konan.library.resolver.KonanResolvedLibrary +import org.jetbrains.kotlin.serialization.deserialization.DeserializedPackageFragment + +private class DeserializedSourceFile( + val name_: String, val index: Int, val library: KonanLibrary) : SourceFile { + override fun getName(): String? = name_ + + override fun equals(other: Any?): Boolean { + return other is DeserializedSourceFile && library == other.library && index == other.index + } + + override fun hashCode(): Int { + return library.hashCode() xor index + } +} + +class SourceFileMap { + private val sourceToIndex = mutableMapOf() + private val indexToSource = mutableMapOf() + + fun assign(file: SourceFile): Int { + return sourceToIndex.getOrPut(file) { + sourceToIndex.size + } + } + + fun provide(fileName: String, index: Int, library: KonanLibrary) { + assert(indexToSource[index] == null) + indexToSource[index] = DeserializedSourceFile(fileName, index, library) + } + + fun sourceFile(index: Int): SourceFile = + indexToSource[index] ?: throw Error("Unknown file for $index") + + fun filesAndClear() = + sourceToIndex.keys.sortedBy { + sourceToIndex[it] + }.also{ + clear() + } + + + fun clear() { + sourceToIndex.clear() + indexToSource.clear() + } +} \ No newline at end of file