[KLIB] Fix explicitlyExported mode
- Refactor deserialization pipeline - Fix K/N test
This commit is contained in:
+60
-51
@@ -55,50 +55,59 @@ abstract class KotlinIrLinker(
|
|||||||
) : DescriptorUniqIdAware, IrDeserializer {
|
) : DescriptorUniqIdAware, IrDeserializer {
|
||||||
|
|
||||||
|
|
||||||
sealed class DeserializationState {
|
sealed class DeserializationState<T> {
|
||||||
val deserializedSymbols = mutableMapOf<UniqId, IrSymbol>()
|
val deserializedSymbols = mutableMapOf<UniqId, IrSymbol>()
|
||||||
val reachableTopLevels = mutableSetOf<UniqId>()
|
|
||||||
val deserializedTopLevels = mutableSetOf<UniqId>()
|
|
||||||
|
|
||||||
operator fun contains(key: UniqId) = key in deserializedSymbols
|
operator fun contains(key: UniqId) = key in deserializedSymbols
|
||||||
operator fun get(key: UniqId): IrSymbol = deserializedSymbols[key] ?: error("No deserialized symbol found for $key")
|
operator fun get(key: UniqId): IrSymbol = deserializedSymbols[key] ?: error("No deserialized symbol found for $key")
|
||||||
|
|
||||||
abstract fun addUniqID(key: UniqId)
|
abstract fun addUniqID(key: UniqId)
|
||||||
protected open fun peekReachableKey(): UniqId? = reachableTopLevels.firstOrNull()
|
abstract fun processPendingDeclarations(processor: (T) -> Unit)
|
||||||
|
|
||||||
|
class ModuleDeserializationState(val module: IrModuleDeserializer): DeserializationState<IrModuleDeserializer.IrDeserializerForFile>() {
|
||||||
|
private val filesWithPendingTopLevels = mutableSetOf<IrModuleDeserializer.IrDeserializerForFile>()
|
||||||
|
|
||||||
|
fun enqueueFile(fileDeserializer: IrModuleDeserializer.IrDeserializerForFile) {
|
||||||
|
filesWithPendingTopLevels.add(fileDeserializer)
|
||||||
|
module.enqueueModule()
|
||||||
|
}
|
||||||
|
|
||||||
class ModuleDeserializationState(val module: IrModuleDeserializer): DeserializationState() {
|
|
||||||
override fun addUniqID(key: UniqId) {
|
override fun addUniqID(key: UniqId) {
|
||||||
module.addModuleReachableTopLevel(key)
|
val fileDeserializer = module.moduleReversedFileIndex[key] ?: error("No file found for key $key")
|
||||||
|
fileDeserializer.fileLocalDeserializationState.addUniqID(key)
|
||||||
|
|
||||||
|
enqueueFile(fileDeserializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun processPendingDeclarations(processor: (IrModuleDeserializer.IrDeserializerForFile) -> Unit) {
|
||||||
|
while (filesWithPendingTopLevels.isNotEmpty()) {
|
||||||
|
val pendingDeserializer = filesWithPendingTopLevels.first()
|
||||||
|
|
||||||
|
processor(pendingDeserializer)
|
||||||
|
|
||||||
|
filesWithPendingTopLevels.remove(pendingDeserializer)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SimpleDeserializationState: DeserializationState() {
|
class SimpleDeserializationState: DeserializationState<UniqId>() {
|
||||||
|
private val reachableTopLevels = mutableSetOf<UniqId>()
|
||||||
|
|
||||||
override fun addUniqID(key: UniqId) {
|
override fun addUniqID(key: UniqId) {
|
||||||
reachableTopLevels.add(key)
|
reachableTopLevels.add(key)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun peekReachableKey(): UniqId {
|
override fun processPendingDeclarations(processor: (UniqId) -> Unit) {
|
||||||
return reachableTopLevels.firstOrNull() ?: error("Expecting non-empty set")
|
while (reachableTopLevels.isNotEmpty()) {
|
||||||
}
|
val reachableKey = reachableTopLevels.first()
|
||||||
}
|
|
||||||
|
|
||||||
fun processPendingDeclaration(processor: (UniqId) -> Unit) {
|
if (deserializedSymbols[reachableKey]?.isBound != true) {
|
||||||
do {
|
processor(reachableKey)
|
||||||
|
}
|
||||||
|
|
||||||
val reachableKey = peekReachableKey() ?: return
|
|
||||||
|
|
||||||
if (deserializedSymbols[reachableKey]?.isBound == true) {
|
|
||||||
reachableTopLevels.remove(reachableKey)
|
reachableTopLevels.remove(reachableKey)
|
||||||
deserializedTopLevels.add(reachableKey)
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
processor(reachableKey)
|
|
||||||
|
|
||||||
reachableTopLevels.remove(reachableKey)
|
|
||||||
deserializedTopLevels.add(reachableKey)
|
|
||||||
|
|
||||||
} while (reachableTopLevels.isNotEmpty())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,7 +132,7 @@ abstract class KotlinIrLinker(
|
|||||||
protected val moduleResolvedForwardDeclarations = mutableMapOf<UniqId, UniqId>()
|
protected val moduleResolvedForwardDeclarations = mutableMapOf<UniqId, UniqId>()
|
||||||
|
|
||||||
private val moduleDeserializationState = DeserializationState.ModuleDeserializationState(this)
|
private val moduleDeserializationState = DeserializationState.ModuleDeserializationState(this)
|
||||||
private val moduleReversedFileIndex = mutableMapOf<UniqId, IrDeserializerForFile>()
|
val moduleReversedFileIndex = mutableMapOf<UniqId, IrDeserializerForFile>()
|
||||||
private val moduleDependencies by lazy {
|
private val moduleDependencies by lazy {
|
||||||
moduleDescriptor.allDependencyModules.filter { it != moduleDescriptor }.map { deserializersForModules[it]!! }
|
moduleDescriptor.allDependencyModules.filter { it != moduleDescriptor }.map { deserializersForModules[it]!! }
|
||||||
}
|
}
|
||||||
@@ -131,7 +140,7 @@ 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 val fileIndex: Int, onlyHeaders: Boolean) :
|
inner class IrDeserializerForFile(private var annotations: List<ProtoConstructorCall>?, private var forcedDeclarations: List<UniqId>?, private val fileIndex: Int, onlyHeaders: Boolean) :
|
||||||
IrFileDeserializer(logger, builtIns, symbolTable) {
|
IrFileDeserializer(logger, builtIns, symbolTable) {
|
||||||
|
|
||||||
private var fileLoops = mutableMapOf<Int, IrLoopBase>()
|
private var fileLoops = mutableMapOf<Int, IrLoopBase>()
|
||||||
@@ -281,7 +290,7 @@ abstract class KotlinIrLinker(
|
|||||||
return moduleDependencies.firstOrNull { key in it.moduleReversedFileIndex }
|
return moduleDependencies.firstOrNull { key in it.moduleReversedFileIndex }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getStateForID(key: UniqId): DeserializationState {
|
private fun getStateForID(key: UniqId): DeserializationState<*> {
|
||||||
if (key.isLocal) return fileLocalDeserializationState
|
if (key.isLocal) return fileLocalDeserializationState
|
||||||
if (isGlobalUniqID(key)) return globalDeserializationState
|
if (isGlobalUniqID(key)) return globalDeserializationState
|
||||||
return getModuleForTopLevelId(key)?.moduleDeserializationState ?: handleNoModuleDeserializerFound(key)
|
return getModuleForTopLevelId(key)?.moduleDeserializationState ?: handleNoModuleDeserializerFound(key)
|
||||||
@@ -371,18 +380,19 @@ abstract class KotlinIrLinker(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deserializeFileAnnotationsIfFirstUse() {
|
fun deserializeFileImplicitDataIfFirstUse() {
|
||||||
annotations?.let {
|
annotations?.let {
|
||||||
file.annotations.addAll(deserializeAnnotations(it))
|
file.annotations.addAll(deserializeAnnotations(it))
|
||||||
annotations = null
|
annotations = null
|
||||||
}
|
}
|
||||||
|
forcedDeclarations?.let {
|
||||||
|
it.forEach { fileLocalDeserializationState.addUniqID(it) }
|
||||||
|
forcedDeclarations = null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deserializeFileTopLevelDeclaration(key: UniqId) {
|
fun deserializeAllFileReachableTopLevel() {
|
||||||
|
fileLocalDeserializationState.processPendingDeclarations {
|
||||||
fileLocalDeserializationState.addUniqID(key)
|
|
||||||
|
|
||||||
fileLocalDeserializationState.processPendingDeclaration {
|
|
||||||
val declaration = deserializeDeclaration(it)
|
val declaration = deserializeDeclaration(it)
|
||||||
file.declarations.add(declaration)
|
file.declarations.add(declaration)
|
||||||
}
|
}
|
||||||
@@ -395,7 +405,10 @@ abstract class KotlinIrLinker(
|
|||||||
|
|
||||||
val fileEntry = NaiveSourceBasedFileEntryImpl(fileName, fileProto.fileEntry.lineStartOffsetsList.toIntArray())
|
val fileEntry = NaiveSourceBasedFileEntryImpl(fileName, fileProto.fileEntry.lineStartOffsetsList.toIntArray())
|
||||||
|
|
||||||
val fileDeserializer = IrDeserializerForFile(fileProto.annotationList, fileIndex, !deserializationStrategy.needBodies)
|
val explicitlyExported = mutableListOf<UniqId>()
|
||||||
|
|
||||||
|
val fileDeserializer =
|
||||||
|
IrDeserializerForFile(fileProto.annotationList, explicitlyExported, fileIndex, !deserializationStrategy.needBodies)
|
||||||
|
|
||||||
val fqName = fileDeserializer.deserializeFqName(fileProto.fqNameList)
|
val fqName = fileDeserializer.deserializeFqName(fileProto.fqNameList)
|
||||||
|
|
||||||
@@ -413,10 +426,8 @@ abstract class KotlinIrLinker(
|
|||||||
moduleReversedFileIndex.getOrPut(it) { fileDeserializer }
|
moduleReversedFileIndex.getOrPut(it) { fileDeserializer }
|
||||||
}
|
}
|
||||||
|
|
||||||
for (d in fileProto.explicitlyExportedToCompilerList) {
|
fileProto.explicitlyExportedToCompilerList.mapTo(explicitlyExported) {
|
||||||
fileDeserializer.run {
|
UniqId(fileDeserializer.loadSymbolData(it).topLevelUniqIdIndex)
|
||||||
fileLocalDeserializationState.addUniqID(UniqId(loadSymbolData(d).topLevelUniqIdIndex))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deserializationStrategy.theWholeWorld) {
|
if (deserializationStrategy.theWholeWorld) {
|
||||||
@@ -425,7 +436,7 @@ abstract class KotlinIrLinker(
|
|||||||
moduleDeserializationState.addUniqID(id)
|
moduleDeserializationState.addUniqID(id)
|
||||||
}
|
}
|
||||||
} else if (deserializationStrategy.explicitlyExported) {
|
} else if (deserializationStrategy.explicitlyExported) {
|
||||||
modulesWithReachableTopLevels.add(this)
|
moduleDeserializationState.enqueueFile(fileDeserializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
return file
|
return file
|
||||||
@@ -444,20 +455,19 @@ abstract class KotlinIrLinker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun deserializeAllModuleReachableTopLevels() {
|
fun deserializeAllModuleReachableTopLevels() {
|
||||||
|
moduleDeserializationState.processPendingDeclarations { fileDeserializer ->
|
||||||
moduleDeserializationState.processPendingDeclaration {
|
fileDeserializer.deserializeFileImplicitDataIfFirstUse()
|
||||||
val fileDeserializer = moduleReversedFileIndex[it]
|
fileDeserializer.deserializeAllFileReachableTopLevel()
|
||||||
?: error("No file deserializer for key $it")
|
|
||||||
|
|
||||||
fileDeserializer.deserializeFileTopLevelDeclaration(it)
|
|
||||||
fileDeserializer.deserializeFileAnnotationsIfFirstUse()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun addModuleReachableTopLevel(topLevelKey: UniqId) {
|
fun enqueueModule() {
|
||||||
moduleDeserializationState.reachableTopLevels.add(topLevelKey)
|
|
||||||
modulesWithReachableTopLevels.add(this)
|
modulesWithReachableTopLevels.add(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun addModuleReachableTopLevel(key: UniqId) {
|
||||||
|
moduleDeserializationState.addUniqID(key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract val descriptorReferenceDeserializer: DescriptorReferenceDeserializer
|
protected abstract val descriptorReferenceDeserializer: DescriptorReferenceDeserializer
|
||||||
@@ -492,7 +502,7 @@ abstract class KotlinIrLinker(
|
|||||||
protected abstract fun readFileCount(moduleDescriptor: ModuleDescriptor): Int
|
protected abstract fun readFileCount(moduleDescriptor: ModuleDescriptor): Int
|
||||||
|
|
||||||
protected abstract fun checkAccessibility(declarationDescriptor: DeclarationDescriptor): Boolean
|
protected abstract fun checkAccessibility(declarationDescriptor: DeclarationDescriptor): Boolean
|
||||||
protected open fun handleNoModuleDeserializerFound(key: UniqId): DeserializationState {
|
protected open fun handleNoModuleDeserializerFound(key: UniqId): DeserializationState<*> {
|
||||||
error("Deserializer for declaration $key is not found")
|
error("Deserializer for declaration $key is not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,7 +525,6 @@ abstract class KotlinIrLinker(
|
|||||||
"Locally accessible declarations should not be accessed here $topLevelDescriptor"
|
"Locally accessible declarations should not be accessed here $topLevelDescriptor"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (topLevelDescriptor !is DeserializedClassDescriptor && topLevelDescriptor !is DeserializedCallableMemberDescriptor) {
|
if (topLevelDescriptor !is DeserializedClassDescriptor && topLevelDescriptor !is DeserializedCallableMemberDescriptor) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
// IGNORE_BACKEND: JVM, JVM_IR
|
||||||
|
// IGNORE_LIGHT_ANALYSIS
|
||||||
|
// MODULE: lib1
|
||||||
|
// FILE: lib1.kt
|
||||||
|
|
||||||
|
// KT-34273
|
||||||
|
|
||||||
|
var foo = "Fail"
|
||||||
|
|
||||||
|
// MODULE: lib2(lib1)
|
||||||
|
// FILE: lib2.kt
|
||||||
|
|
||||||
|
private val bar = run {
|
||||||
|
foo = "OK"
|
||||||
|
42
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// MODULE: main(lib1, lib2)
|
||||||
|
// FILE: main.kt
|
||||||
|
|
||||||
|
// TODO: the proper behaviour of this test is still open design issue
|
||||||
|
// K/N & K/JS used to go like this when JVM fails
|
||||||
|
|
||||||
|
fun box(): String = foo
|
||||||
+5
@@ -18674,6 +18674,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/properties/protectedJavaPropertyInCompanion.kt");
|
runTest("compiler/testData/codegen/box/properties/protectedJavaPropertyInCompanion.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sideEffectInTopLevelInitializerMultiModule.kt")
|
||||||
|
public void testSideEffectInTopLevelInitializerMultiModule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/properties/sideEffectInTopLevelInitializerMultiModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("substituteJavaSuperField.kt")
|
@TestMetadata("substituteJavaSuperField.kt")
|
||||||
public void testSubstituteJavaSuperField() throws Exception {
|
public void testSubstituteJavaSuperField() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/properties/substituteJavaSuperField.kt");
|
runTest("compiler/testData/codegen/box/properties/substituteJavaSuperField.kt");
|
||||||
|
|||||||
+5
@@ -18336,6 +18336,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/properties/augmentedAssignmentsAndIncrements.kt");
|
runTest("compiler/testData/codegen/box/properties/augmentedAssignmentsAndIncrements.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sideEffectInTopLevelInitializerMultiModule.kt")
|
||||||
|
public void ignoreSideEffectInTopLevelInitializerMultiModule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/properties/sideEffectInTopLevelInitializerMultiModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
private void runTest(String testDataFilePath) throws Exception {
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||||
}
|
}
|
||||||
|
|||||||
+5
@@ -17554,6 +17554,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/properties/protectedJavaPropertyInCompanion.kt");
|
runTest("compiler/testData/codegen/box/properties/protectedJavaPropertyInCompanion.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sideEffectInTopLevelInitializerMultiModule.kt")
|
||||||
|
public void testSideEffectInTopLevelInitializerMultiModule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/properties/sideEffectInTopLevelInitializerMultiModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("substituteJavaSuperField.kt")
|
@TestMetadata("substituteJavaSuperField.kt")
|
||||||
public void testSubstituteJavaSuperField() throws Exception {
|
public void testSubstituteJavaSuperField() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/properties/substituteJavaSuperField.kt");
|
runTest("compiler/testData/codegen/box/properties/substituteJavaSuperField.kt");
|
||||||
|
|||||||
Generated
+5
@@ -14494,6 +14494,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/properties/privatePropertyWithoutBackingField.kt");
|
runTest("compiler/testData/codegen/box/properties/privatePropertyWithoutBackingField.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sideEffectInTopLevelInitializerMultiModule.kt")
|
||||||
|
public void testSideEffectInTopLevelInitializerMultiModule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/properties/sideEffectInTopLevelInitializerMultiModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("twoAnnotatedExtensionPropertiesWithoutBackingFields.kt")
|
@TestMetadata("twoAnnotatedExtensionPropertiesWithoutBackingFields.kt")
|
||||||
public void testTwoAnnotatedExtensionPropertiesWithoutBackingFields() throws Exception {
|
public void testTwoAnnotatedExtensionPropertiesWithoutBackingFields() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/properties/twoAnnotatedExtensionPropertiesWithoutBackingFields.kt");
|
runTest("compiler/testData/codegen/box/properties/twoAnnotatedExtensionPropertiesWithoutBackingFields.kt");
|
||||||
|
|||||||
+5
@@ -15649,6 +15649,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/properties/privatePropertyWithoutBackingField.kt");
|
runTest("compiler/testData/codegen/box/properties/privatePropertyWithoutBackingField.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("sideEffectInTopLevelInitializerMultiModule.kt")
|
||||||
|
public void testSideEffectInTopLevelInitializerMultiModule() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/properties/sideEffectInTopLevelInitializerMultiModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("twoAnnotatedExtensionPropertiesWithoutBackingFields.kt")
|
@TestMetadata("twoAnnotatedExtensionPropertiesWithoutBackingFields.kt")
|
||||||
public void testTwoAnnotatedExtensionPropertiesWithoutBackingFields() throws Exception {
|
public void testTwoAnnotatedExtensionPropertiesWithoutBackingFields() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/properties/twoAnnotatedExtensionPropertiesWithoutBackingFields.kt");
|
runTest("compiler/testData/codegen/box/properties/twoAnnotatedExtensionPropertiesWithoutBackingFields.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user