Deserializer: Fix initialization order
Top-level initializers must be deserialized in the same order they where in the original source file. Before this patch this rule might be violated. Consider the following case: // lib1.kt val a = 5 val b = a * 5 // lib2.kt fun foo() = println(b) Compile both files into libraries and then link an application against them. During deserialization of lib2 'b' will be added to the deserialization queue of lib1. After that we will add 'a' to this queue too. Thus 'b' and 'a' will be in a wrong order in this queue resulting in a wrong order of corresponding top-level initializers in a final executable. This patch fixes this issue by adding all top-level initializers to a deserialization queue before all other declarations.
This commit is contained in:
+13
-14
@@ -91,7 +91,7 @@ abstract class KotlinIrLinker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
class SimpleDeserializationState: DeserializationState<UniqId>() {
|
class SimpleDeserializationState: DeserializationState<UniqId>() {
|
||||||
private val reachableTopLevels = mutableSetOf<UniqId>()
|
private val reachableTopLevels = LinkedHashSet<UniqId>()
|
||||||
|
|
||||||
override fun addUniqID(key: UniqId) {
|
override fun addUniqID(key: UniqId) {
|
||||||
reachableTopLevels.add(key)
|
reachableTopLevels.add(key)
|
||||||
@@ -140,8 +140,11 @@ abstract class KotlinIrLinker(
|
|||||||
// This is a heavy initializer
|
// This is a heavy initializer
|
||||||
val module = deserializeIrModuleHeader()
|
val module = deserializeIrModuleHeader()
|
||||||
|
|
||||||
inner class IrDeserializerForFile(private var annotations: List<ProtoConstructorCall>?, private var forcedDeclarations: List<UniqId>?, private val fileIndex: Int, onlyHeaders: Boolean) :
|
inner class IrDeserializerForFile(
|
||||||
IrFileDeserializer(logger, builtIns, symbolTable) {
|
private var annotations: List<ProtoConstructorCall>?,
|
||||||
|
private val fileIndex: Int,
|
||||||
|
onlyHeaders: Boolean
|
||||||
|
) : IrFileDeserializer(logger, builtIns, symbolTable) {
|
||||||
|
|
||||||
private var fileLoops = mutableMapOf<Int, IrLoopBase>()
|
private var fileLoops = mutableMapOf<Int, IrLoopBase>()
|
||||||
|
|
||||||
@@ -385,10 +388,6 @@ abstract class KotlinIrLinker(
|
|||||||
file.annotations.addAll(deserializeAnnotations(it))
|
file.annotations.addAll(deserializeAnnotations(it))
|
||||||
annotations = null
|
annotations = null
|
||||||
}
|
}
|
||||||
forcedDeclarations?.let {
|
|
||||||
it.forEach { fileLocalDeserializationState.addUniqID(it) }
|
|
||||||
forcedDeclarations = null
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deserializeAllFileReachableTopLevel() {
|
fun deserializeAllFileReachableTopLevel() {
|
||||||
@@ -405,10 +404,14 @@ abstract class KotlinIrLinker(
|
|||||||
|
|
||||||
val fileEntry = NaiveSourceBasedFileEntryImpl(fileName, fileProto.fileEntry.lineStartOffsetsList.toIntArray())
|
val fileEntry = NaiveSourceBasedFileEntryImpl(fileName, fileProto.fileEntry.lineStartOffsetsList.toIntArray())
|
||||||
|
|
||||||
val explicitlyExported = mutableListOf<UniqId>()
|
|
||||||
|
|
||||||
val fileDeserializer =
|
val fileDeserializer =
|
||||||
IrDeserializerForFile(fileProto.annotationList, explicitlyExported, fileIndex, !deserializationStrategy.needBodies)
|
IrDeserializerForFile(fileProto.annotationList, fileIndex, !deserializationStrategy.needBodies).apply {
|
||||||
|
// Explicitly exported declarations (e.g. top-level initializers) must be deserialized before all other declarations.
|
||||||
|
// Thus we schedule their deserialization in deserializer's constructor.
|
||||||
|
fileProto.explicitlyExportedToCompilerList.forEach {
|
||||||
|
fileLocalDeserializationState.addUniqID(UniqId(loadSymbolData(it).topLevelUniqIdIndex))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val fqName = fileDeserializer.deserializeFqName(fileProto.fqNameList)
|
val fqName = fileDeserializer.deserializeFqName(fileProto.fqNameList)
|
||||||
|
|
||||||
@@ -426,10 +429,6 @@ abstract class KotlinIrLinker(
|
|||||||
moduleReversedFileIndex.getOrPut(it) { fileDeserializer }
|
moduleReversedFileIndex.getOrPut(it) { fileDeserializer }
|
||||||
}
|
}
|
||||||
|
|
||||||
fileProto.explicitlyExportedToCompilerList.mapTo(explicitlyExported) {
|
|
||||||
UniqId(fileDeserializer.loadSymbolData(it).topLevelUniqIdIndex)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (deserializationStrategy.theWholeWorld) {
|
if (deserializationStrategy.theWholeWorld) {
|
||||||
for (id in fileUniqIdIndex) {
|
for (id in fileUniqIdIndex) {
|
||||||
assert(id.isPublic)
|
assert(id.isPublic)
|
||||||
|
|||||||
Reference in New Issue
Block a user