From 40602d47ecc083d6fdebc57028788736f63a5247 Mon Sep 17 00:00:00 2001 From: SvyatoslavScherbina Date: Fri, 5 Jun 2020 14:43:43 +0300 Subject: [PATCH] Fix missing "outer this" field in cached super inner classes #KT-39153 Fixed --- .../jetbrains/kotlin/backend/konan/Context.kt | 2 +- .../kotlin/backend/konan/ToplevelPhases.kt | 9 +++++++++ .../konan/descriptors/ClassLayoutBuilder.kt | 13 +++++++++++-- .../backend/konan/lower/InnerClassLowering.kt | 17 +++++++++++------ 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt index 3dc4edb0dc4..c633658725b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/Context.kt @@ -254,7 +254,7 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) { val layoutBuilders = mutableMapOf() fun getLayoutBuilder(irClass: IrClass) = layoutBuilders.getOrPut(irClass) { - ClassLayoutBuilder(irClass, this) + ClassLayoutBuilder(irClass, this, isLowered = shouldLower(this, irClass)) } lateinit var globalHierarchyAnalysisResult: GlobalHierarchyAnalysisResult diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt index fbf300786e8..e829e4d462b 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/ToplevelPhases.kt @@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor import org.jetbrains.kotlin.descriptors.konan.DeserializedKlibModuleOrigin import org.jetbrains.kotlin.descriptors.konan.KlibModuleOrigin import org.jetbrains.kotlin.descriptors.konan.isNativeStdlib +import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrFile import org.jetbrains.kotlin.ir.declarations.IrModuleFragment import org.jetbrains.kotlin.ir.symbols.IrSymbol @@ -256,7 +257,10 @@ internal val psiToIrPhase = konanUnitPhase( linker.modules.values.forEach{ fakeOverrideChecker.check(it) } irModule = module + + // Note: coupled with [shouldLower] below. irModules = linker.modules.filterValues { llvmModuleSpecification.containsModule(it) } + ir.symbols = symbols functionIrClassFactory.module = @@ -268,6 +272,11 @@ internal val psiToIrPhase = konanUnitPhase( prerequisite = setOf(createSymbolTablePhase) ) +// Coupled with [psiToIrPhase] logic above. +internal fun shouldLower(context: Context, declaration: IrDeclaration): Boolean { + return context.llvmModuleSpecification.containsDeclaration(declaration) +} + internal val destroySymbolTablePhase = konanUnitPhase( op = { this.symbolTable = null // TODO: invalidate symbolTable itself. diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt index 091d1dc447e..7902b89f91c 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassLayoutBuilder.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.backend.konan.llvm.llvmType import org.jetbrains.kotlin.backend.konan.llvm.localHash +import org.jetbrains.kotlin.backend.konan.lower.InnerClassLowering import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.IrElement @@ -260,7 +261,7 @@ internal class GlobalHierarchyAnalysis(val context: Context, val irModule: IrMod } } -internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) { +internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context, val isLowered: Boolean) { private val DEBUG = 0 private inline fun DEBUG_OUTPUT(severity: Int, block: () -> Unit) { @@ -432,7 +433,15 @@ internal class ClassLayoutBuilder(val irClass: IrClass, val context: Context) { * Fields declared in the class. */ private fun getDeclaredFields(): List { - val fields = irClass.declarations.mapNotNull { + val declarations: List = if (irClass.isInner && !isLowered) { + // Note: copying to avoid mutation of the original class. + irClass.declarations.toMutableList() + .also { InnerClassLowering.addOuterThisField(it, irClass, context) } + } else { + irClass.declarations + } + + val fields = declarations.mapNotNull { when (it) { is IrField -> it.takeIf { it.isReal } is IrProperty -> it.takeIf { it.isReal }?.backingField diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt index b5f261ae6f6..ff1022f50d5 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/InnerClassLowering.kt @@ -9,9 +9,7 @@ import org.jetbrains.kotlin.backend.common.ClassLoweringPass import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.lower.callsSuper import org.jetbrains.kotlin.backend.konan.Context -import org.jetbrains.kotlin.ir.declarations.IrClass -import org.jetbrains.kotlin.ir.declarations.IrConstructor -import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrBlockBody import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrGetValue @@ -20,7 +18,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol -import org.jetbrains.kotlin.ir.types.IrSimpleType import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.util.dump import org.jetbrains.kotlin.ir.util.parentAsClass @@ -32,6 +29,14 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { InnerClassTransformer(irClass).lowerInnerClass() } + companion object { + fun addOuterThisField(declarations: MutableList, irClass: IrClass, context: Context): IrField { + val outerThisField = context.specialDeclarationsFactory.getOuterThisField(irClass) + declarations += outerThisField + return outerThisField + } + } + private inner class InnerClassTransformer(val irClass: IrClass) { lateinit var outerThisFieldSymbol: IrFieldSymbol @@ -44,8 +49,8 @@ internal class InnerClassLowering(val context: Context) : ClassLoweringPass { } private fun createOuterThisField() { - irClass.declarations += context.specialDeclarationsFactory.getOuterThisField(irClass) - outerThisFieldSymbol = context.specialDeclarationsFactory.getOuterThisField(irClass).symbol + val outerThisField = addOuterThisField(irClass.declarations, irClass, context) + outerThisFieldSymbol = outerThisField.symbol } private fun lowerConstructors() {