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 91e7cb50041..22545b4141f 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 @@ -29,6 +29,7 @@ import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter import org.jetbrains.kotlin.backend.konan.library.LinkData import org.jetbrains.kotlin.backend.konan.llvm.* import org.jetbrains.kotlin.backend.konan.lower.DECLARATION_ORIGIN_BRIDGE_METHOD +import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl @@ -49,6 +50,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext import org.jetbrains.kotlin.resolve.DescriptorUtils @@ -93,7 +95,7 @@ internal class SpecialDeclarationsFactory(val context: Context) { { "Function $descriptor is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor.descriptor}" }) val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections return bridgesDescriptors.getOrPut(irFunction to bridgeDirections) { - val newDescriptor = SimpleFunctionDescriptorImpl.create( + val bridgeDescriptor = SimpleFunctionDescriptorImpl.create( /* containingDeclaration = */ descriptor.containingDeclaration, /* annotations = */ Annotations.EMPTY, /* name = */ "${irFunction.functionName}".synthesizedName, @@ -105,8 +107,8 @@ internal class SpecialDeclarationsFactory(val context: Context) { IrFunctionImpl( irFunction.startOffset, irFunction.endOffset, - DECLARATION_ORIGIN_BRIDGE_METHOD, - newDescriptor + DECLARATION_ORIGIN_BRIDGE_METHOD(irFunction), + bridgeDescriptor ).apply { createParameterDeclarations() this.parent = overriddenFunctionDescriptor.descriptor.parent diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassVtablesBuilder.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassVtablesBuilder.kt index 9094607dd5e..cfdb5a13642 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassVtablesBuilder.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/descriptors/ClassVtablesBuilder.kt @@ -20,6 +20,7 @@ import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.backend.konan.llvm.localHash +import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.util.simpleFunctions @@ -180,12 +181,11 @@ internal class ClassVtablesBuilder(val classDescriptor: ClassDescriptor, val con // TODO: probably method table should contain all accessible methods to improve binary compatibility } -} + private val IrClass.sortedOverridableOrOverridingMethods: List + get() = + this.simpleFunctions() + .filter { (it.isOverridable || it.overriddenSymbols.isNotEmpty()) + && it.bridgeTarget == null } + .sortedBy { it.functionName.localHash.value } -private val IrClass.sortedOverridableOrOverridingMethods: List - get() = - this.simpleFunctions() - .filter { it.isOverridable || it.overriddenSymbols.isNotEmpty() } - // TODO: extract method .isBridge() - .filterNot { it.name.asString().contains(" FunctionSymbol.external(functionSymbol.hash, numberOfParameters, isGlobalInitializer, @@ -793,11 +798,11 @@ internal object DFGSerializer { is DataFlowIR.FunctionSymbol.Public -> FunctionSymbol.public(functionSymbol.hash, numberOfParameters, - isGlobalInitializer, functionSymbol.symbolTableIndex, name) + isGlobalInitializer, functionSymbol.symbolTableIndex, bridgeTarget, name) is DataFlowIR.FunctionSymbol.Private -> FunctionSymbol.private(functionSymbol.symbolTableIndex, numberOfParameters, - isGlobalInitializer, name) + isGlobalInitializer, bridgeTarget, name) else -> error("Unknown function symbol $functionSymbol") } @@ -956,7 +961,7 @@ internal object DFGSerializer { if (symbolTableIndex >= 0) ++module.numberOfFunctions DataFlowIR.FunctionSymbol.Public(public.hash, public.numberOfParameters, module, - symbolTableIndex, public.isGlobalInitializer, public.name).also { + symbolTableIndex, public.isGlobalInitializer, null, public.name).also { publicFunctionsMap.put(it.hash, it) } } @@ -966,7 +971,7 @@ internal object DFGSerializer { if (symbolTableIndex >= 0) ++module.numberOfFunctions DataFlowIR.FunctionSymbol.Private(privateFunIndex++, private.numberOfParameters, module, - symbolTableIndex, private.isGlobalInitializer, private.name) + symbolTableIndex, private.isGlobalInitializer, null, private.name) } } } @@ -991,6 +996,16 @@ internal object DFGSerializer { } } + symbolTable.functionSymbols.forEachIndexed { index, symbol -> + val deserializedSymbol = functionSymbols[index] as? DataFlowIR.FunctionSymbol.Declared + ?: return@forEachIndexed + val bridgeTarget = if (deserializedSymbol is DataFlowIR.FunctionSymbol.Public) + symbol.public!!.bridgeTarget + else + symbol.private!!.bridgeTarget + deserializedSymbol.bridgeTarget = bridgeTarget?.let { functionSymbols[it] } + } + fun deserializeEdge(edge: Edge) = DataFlowIR.Edge(edge.castToType?.let { types[it] }) diff --git a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt index 4aa3bd58b73..1a882ac8fb1 100644 --- a/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt +++ b/backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/optimizations/DataFlowIR.kt @@ -27,6 +27,7 @@ import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.backend.konan.llvm.isExported import org.jetbrains.kotlin.backend.konan.llvm.localHash import org.jetbrains.kotlin.backend.konan.llvm.symbolName +import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.ModuleDescriptor @@ -37,6 +38,7 @@ import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid +import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.constants.ConstantValue @@ -139,12 +141,14 @@ internal object DataFlowIR { } abstract class Declared(numberOfParameters: Int, val module: Module, val symbolTableIndex: Int, - isGlobalInitializer: Boolean, name: String?) - : FunctionSymbol(numberOfParameters, isGlobalInitializer, name) + isGlobalInitializer: Boolean, var bridgeTarget: FunctionSymbol?, name: String?) + : FunctionSymbol(numberOfParameters, isGlobalInitializer, name) { + + } class Public(val hash: Long, numberOfParameters: Int, module: Module, symbolTableIndex: Int, - isGlobalInitializer: Boolean, name: String? = null) - : Declared(numberOfParameters, module, symbolTableIndex, isGlobalInitializer, name) { + isGlobalInitializer: Boolean, bridgeTarget: FunctionSymbol?, name: String? = null) + : Declared(numberOfParameters, module, symbolTableIndex, isGlobalInitializer, bridgeTarget, name) { override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is Public) return false @@ -162,8 +166,8 @@ internal object DataFlowIR { } class Private(val index: Int, numberOfParameters: Int, module: Module, symbolTableIndex: Int, - isGlobalInitializer: Boolean, name: String? = null) - : Declared(numberOfParameters, module, symbolTableIndex, isGlobalInitializer, name) { + isGlobalInitializer: Boolean, bridgeTarget: FunctionSymbol?, name: String? = null) + : Declared(numberOfParameters, module, symbolTableIndex, isGlobalInitializer, bridgeTarget, name) { override fun equals(other: Any?): Boolean { if (this === other) return true if (other !is Private) return false @@ -509,13 +513,13 @@ internal object DataFlowIR { private val FunctionDescriptor.internalName get() = getFqName(this).asString() + "#internal" - fun mapFunction(descriptor: DeclarationDescriptor) = descriptor.original.let { + fun mapFunction(descriptor: DeclarationDescriptor): FunctionSymbol = descriptor.original.let { functionMap.getOrPut(it) { when (it) { is IrField -> { // A global property initializer. assert (it.parent !is IrClass) { "All local properties initializers should've been lowered" } - FunctionSymbol.Private(privateFunIndex++, 0, module, -1, true, takeName { "${it.symbolName}_init" }) + FunctionSymbol.Private(privateFunIndex++, 0, module, -1, true, null, takeName { "${it.symbolName}_init" }) } is FunctionDescriptor -> { @@ -533,14 +537,20 @@ internal object DataFlowIR { } else { val isAbstract = it is SimpleFunctionDescriptor && it.modality == Modality.ABSTRACT val classDescriptor = it.containingDeclaration as? ClassDescriptor + val bridgeTarget = it.bridgeTarget + val isSpecialBridge = bridgeTarget.let { + it != null && BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(it.descriptor) != null + } + val bridgeTargetSymbol = if (isSpecialBridge || bridgeTarget == null) null else mapFunction(bridgeTarget) + val placeToFunctionsTable = !isAbstract && it !is ConstructorDescriptor && classDescriptor != null && classDescriptor.kind != ClassKind.ANNOTATION_CLASS - && (it.isOverridableOrOverrides || it.name.asString().contains("