DFG: Added bridge target for bridge symbols

This commit is contained in:
Igor Chevdar
2018-04-23 18:38:15 +03:00
parent 8e1caefea6
commit b46d19c1ac
5 changed files with 69 additions and 36 deletions
@@ -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.library.LinkData
import org.jetbrains.kotlin.backend.konan.llvm.* 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.DECLARATION_ORIGIN_BRIDGE_METHOD
import org.jetbrains.kotlin.backend.konan.lower.bridgeTarget
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl 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.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.konan.target.CompilerOutputKind import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
import org.jetbrains.kotlin.resolve.DescriptorUtils 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}" }) { "Function $descriptor is not needed in a bridge to call overridden function ${overriddenFunctionDescriptor.overriddenDescriptor.descriptor}" })
val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections val bridgeDirections = overriddenFunctionDescriptor.bridgeDirections
return bridgesDescriptors.getOrPut(irFunction to bridgeDirections) { return bridgesDescriptors.getOrPut(irFunction to bridgeDirections) {
val newDescriptor = SimpleFunctionDescriptorImpl.create( val bridgeDescriptor = SimpleFunctionDescriptorImpl.create(
/* containingDeclaration = */ descriptor.containingDeclaration, /* containingDeclaration = */ descriptor.containingDeclaration,
/* annotations = */ Annotations.EMPTY, /* annotations = */ Annotations.EMPTY,
/* name = */ "<bridge-$bridgeDirections>${irFunction.functionName}".synthesizedName, /* name = */ "<bridge-$bridgeDirections>${irFunction.functionName}".synthesizedName,
@@ -105,8 +107,8 @@ internal class SpecialDeclarationsFactory(val context: Context) {
IrFunctionImpl( IrFunctionImpl(
irFunction.startOffset, irFunction.startOffset,
irFunction.endOffset, irFunction.endOffset,
DECLARATION_ORIGIN_BRIDGE_METHOD, DECLARATION_ORIGIN_BRIDGE_METHOD(irFunction),
newDescriptor bridgeDescriptor
).apply { ).apply {
createParameterDeclarations() createParameterDeclarations()
this.parent = overriddenFunctionDescriptor.descriptor.parent this.parent = overriddenFunctionDescriptor.descriptor.parent
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.irasdescriptors.* import org.jetbrains.kotlin.backend.konan.irasdescriptors.*
import org.jetbrains.kotlin.backend.konan.llvm.functionName import org.jetbrains.kotlin.backend.konan.llvm.functionName
import org.jetbrains.kotlin.backend.konan.llvm.localHash 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.descriptors.Modality
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.util.simpleFunctions 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 // TODO: probably method table should contain all accessible methods to improve binary compatibility
} }
} private val IrClass.sortedOverridableOrOverridingMethods: List<SimpleFunctionDescriptor>
get() =
this.simpleFunctions()
.filter { (it.isOverridable || it.overriddenSymbols.isNotEmpty())
&& it.bridgeTarget == null }
.sortedBy { it.functionName.localHash.value }
private val IrClass.sortedOverridableOrOverridingMethods: List<SimpleFunctionDescriptor> }
get() =
this.simpleFunctions()
.filter { it.isOverridable || it.overriddenSymbols.isNotEmpty() }
// TODO: extract method .isBridge()
.filterNot { it.name.asString().contains("<bridge-") }
.sortedBy { it.functionName.localHash.value }
@@ -177,8 +177,14 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
} }
} }
internal object DECLARATION_ORIGIN_BRIDGE_METHOD : internal class DECLARATION_ORIGIN_BRIDGE_METHOD(val bridgeTarget: IrFunction) : IrDeclarationOrigin {
IrDeclarationOriginImpl("BRIDGE_METHOD") override fun toString(): String {
return "BRIDGE_METHOD(target=${bridgeTarget.descriptor})"
}
}
internal val IrFunction.bridgeTarget: IrFunction?
get() = (origin as? DECLARATION_ORIGIN_BRIDGE_METHOD)?.bridgeTarget
private fun IrBuilderWithScope.returnIfBadType(value: IrExpression, private fun IrBuilderWithScope.returnIfBadType(value: IrExpression,
type: KotlinType, type: KotlinType,
@@ -315,28 +315,32 @@ internal object DFGSerializer {
} }
class PublicFunctionSymbol(val hash: Long, val numberOfParameters: Int, val isGlobalInitializer: Boolean, class PublicFunctionSymbol(val hash: Long, val numberOfParameters: Int, val isGlobalInitializer: Boolean,
val index: Int, val name: String?) { val index: Int, val bridgeTarget: Int?, val name: String?) {
constructor(data: ArraySlice) : this(data.readLong(), data.readInt(), data.readBoolean(), data.readInt(), constructor(data: ArraySlice) : this(data.readLong(), data.readInt(), data.readBoolean(), data.readInt(),
data.readNullableString()) data.readNullableInt(), data.readNullableString())
fun write(result: ArraySlice) { fun write(result: ArraySlice) {
result.writeLong(hash) result.writeLong(hash)
result.writeInt(numberOfParameters) result.writeInt(numberOfParameters)
result.writeBoolean(isGlobalInitializer) result.writeBoolean(isGlobalInitializer)
result.writeInt(index) result.writeInt(index)
result.writeNullableInt(bridgeTarget)
result.writeNullableString(name) result.writeNullableString(name)
} }
} }
class PrivateFunctionSymbol(val index: Int, val numberOfParameters: Int, val isGlobalInitializer: Boolean, val name: String?) { class PrivateFunctionSymbol(val index: Int, val numberOfParameters: Int, val isGlobalInitializer: Boolean,
val bridgeTarget: Int?, val name: String?) {
constructor(data: ArraySlice) : this(data.readInt(), data.readInt(), data.readBoolean(), data.readNullableString()) constructor(data: ArraySlice) : this(data.readInt(), data.readInt(), data.readBoolean(),
data.readNullableInt(), data.readNullableString())
fun write(result: ArraySlice) { fun write(result: ArraySlice) {
result.writeInt(index) result.writeInt(index)
result.writeInt(numberOfParameters) result.writeInt(numberOfParameters)
result.writeBoolean(isGlobalInitializer) result.writeBoolean(isGlobalInitializer)
result.writeNullableInt(bridgeTarget)
result.writeNullableString(name) result.writeNullableString(name)
} }
} }
@@ -361,11 +365,11 @@ internal object DFGSerializer {
fun external(hash: Long, numberOfParameters: Int, isGlobalInitializer: Boolean, escapes: Int?, pointsTo: IntArray?, name: String?) = fun external(hash: Long, numberOfParameters: Int, isGlobalInitializer: Boolean, escapes: Int?, pointsTo: IntArray?, name: String?) =
FunctionSymbol(ExternalFunctionSymbol(hash, numberOfParameters, isGlobalInitializer, escapes, pointsTo, name), null, null) FunctionSymbol(ExternalFunctionSymbol(hash, numberOfParameters, isGlobalInitializer, escapes, pointsTo, name), null, null)
fun public(hash: Long, numberOfParameters: Int, isGlobalInitializer: Boolean, index: Int, name: String?) = fun public(hash: Long, numberOfParameters: Int, isGlobalInitializer: Boolean, index: Int, bridgeTarget: Int?, name: String?) =
FunctionSymbol(null, PublicFunctionSymbol(hash, numberOfParameters, isGlobalInitializer, index, name), null) FunctionSymbol(null, PublicFunctionSymbol(hash, numberOfParameters, isGlobalInitializer, index, bridgeTarget, name), null)
fun private(index: Int, numberOfParameters: Int, isGlobalInitializer: Boolean, name: String?) = fun private(index: Int, numberOfParameters: Int, isGlobalInitializer: Boolean, bridgeTarget: Int?, name: String?) =
FunctionSymbol(null, null, PrivateFunctionSymbol(index, numberOfParameters, isGlobalInitializer, name)) FunctionSymbol(null, null, PrivateFunctionSymbol(index, numberOfParameters, isGlobalInitializer, bridgeTarget, name))
fun read(data: ArraySlice): FunctionSymbol { fun read(data: ArraySlice): FunctionSymbol {
val tag = data.readByte().toInt() val tag = data.readByte().toInt()
@@ -786,6 +790,7 @@ internal object DFGSerializer {
val numberOfParameters = functionSymbol.numberOfParameters val numberOfParameters = functionSymbol.numberOfParameters
val isGlobalInitializer = functionSymbol.isGlobalInitializer val isGlobalInitializer = functionSymbol.isGlobalInitializer
val name = functionSymbol.name val name = functionSymbol.name
val bridgeTarget = (functionSymbol as? DataFlowIR.FunctionSymbol.Declared)?.let { functionSymbolMap[it] }
when (functionSymbol) { when (functionSymbol) {
is DataFlowIR.FunctionSymbol.External -> is DataFlowIR.FunctionSymbol.External ->
FunctionSymbol.external(functionSymbol.hash, numberOfParameters, isGlobalInitializer, FunctionSymbol.external(functionSymbol.hash, numberOfParameters, isGlobalInitializer,
@@ -793,11 +798,11 @@ internal object DFGSerializer {
is DataFlowIR.FunctionSymbol.Public -> is DataFlowIR.FunctionSymbol.Public ->
FunctionSymbol.public(functionSymbol.hash, numberOfParameters, FunctionSymbol.public(functionSymbol.hash, numberOfParameters,
isGlobalInitializer, functionSymbol.symbolTableIndex, name) isGlobalInitializer, functionSymbol.symbolTableIndex, bridgeTarget, name)
is DataFlowIR.FunctionSymbol.Private -> is DataFlowIR.FunctionSymbol.Private ->
FunctionSymbol.private(functionSymbol.symbolTableIndex, numberOfParameters, FunctionSymbol.private(functionSymbol.symbolTableIndex, numberOfParameters,
isGlobalInitializer, name) isGlobalInitializer, bridgeTarget, name)
else -> error("Unknown function symbol $functionSymbol") else -> error("Unknown function symbol $functionSymbol")
} }
@@ -956,7 +961,7 @@ internal object DFGSerializer {
if (symbolTableIndex >= 0) if (symbolTableIndex >= 0)
++module.numberOfFunctions ++module.numberOfFunctions
DataFlowIR.FunctionSymbol.Public(public.hash, public.numberOfParameters, module, 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) publicFunctionsMap.put(it.hash, it)
} }
} }
@@ -966,7 +971,7 @@ internal object DFGSerializer {
if (symbolTableIndex >= 0) if (symbolTableIndex >= 0)
++module.numberOfFunctions ++module.numberOfFunctions
DataFlowIR.FunctionSymbol.Private(privateFunIndex++, private.numberOfParameters, module, 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) = fun deserializeEdge(edge: Edge) =
DataFlowIR.Edge(edge.castToType?.let { types[it] }) DataFlowIR.Edge(edge.castToType?.let { types[it] })
@@ -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.isExported
import org.jetbrains.kotlin.backend.konan.llvm.localHash import org.jetbrains.kotlin.backend.konan.llvm.localHash
import org.jetbrains.kotlin.backend.konan.llvm.symbolName 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.ClassKind
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.ModuleDescriptor 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.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid 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.FqName
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.constants.ConstantValue 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, abstract class Declared(numberOfParameters: Int, val module: Module, val symbolTableIndex: Int,
isGlobalInitializer: Boolean, name: String?) isGlobalInitializer: Boolean, var bridgeTarget: FunctionSymbol?, name: String?)
: FunctionSymbol(numberOfParameters, isGlobalInitializer, name) : FunctionSymbol(numberOfParameters, isGlobalInitializer, name) {
}
class Public(val hash: Long, numberOfParameters: Int, module: Module, symbolTableIndex: Int, class Public(val hash: Long, numberOfParameters: Int, module: Module, symbolTableIndex: Int,
isGlobalInitializer: Boolean, name: String? = null) isGlobalInitializer: Boolean, bridgeTarget: FunctionSymbol?, name: String? = null)
: Declared(numberOfParameters, module, symbolTableIndex, isGlobalInitializer, name) { : Declared(numberOfParameters, module, symbolTableIndex, isGlobalInitializer, bridgeTarget, name) {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Public) return false if (other !is Public) return false
@@ -162,8 +166,8 @@ internal object DataFlowIR {
} }
class Private(val index: Int, numberOfParameters: Int, module: Module, symbolTableIndex: Int, class Private(val index: Int, numberOfParameters: Int, module: Module, symbolTableIndex: Int,
isGlobalInitializer: Boolean, name: String? = null) isGlobalInitializer: Boolean, bridgeTarget: FunctionSymbol?, name: String? = null)
: Declared(numberOfParameters, module, symbolTableIndex, isGlobalInitializer, name) { : Declared(numberOfParameters, module, symbolTableIndex, isGlobalInitializer, bridgeTarget, name) {
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (this === other) return true if (this === other) return true
if (other !is Private) return false if (other !is Private) return false
@@ -509,13 +513,13 @@ internal object DataFlowIR {
private val FunctionDescriptor.internalName get() = getFqName(this).asString() + "#internal" 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) { functionMap.getOrPut(it) {
when (it) { when (it) {
is IrField -> { is IrField -> {
// A global property initializer. // A global property initializer.
assert (it.parent !is IrClass) { "All local properties initializers should've been lowered" } 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 -> { is FunctionDescriptor -> {
@@ -533,14 +537,20 @@ internal object DataFlowIR {
} else { } else {
val isAbstract = it is SimpleFunctionDescriptor && it.modality == Modality.ABSTRACT val isAbstract = it is SimpleFunctionDescriptor && it.modality == Modality.ABSTRACT
val classDescriptor = it.containingDeclaration as? ClassDescriptor 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 val placeToFunctionsTable = !isAbstract && it !is ConstructorDescriptor && classDescriptor != null
&& classDescriptor.kind != ClassKind.ANNOTATION_CLASS && classDescriptor.kind != ClassKind.ANNOTATION_CLASS
&& (it.isOverridableOrOverrides || it.name.asString().contains("<bridge-") || !classDescriptor.isFinal()) && (it.isOverridableOrOverrides || bridgeTarget != null || !classDescriptor.isFinal())
val symbolTableIndex = if (placeToFunctionsTable) module.numberOfFunctions++ else -1 val symbolTableIndex = if (placeToFunctionsTable) module.numberOfFunctions++ else -1
if (it.isExported()) if (it.isExported())
FunctionSymbol.Public(name.localHash.value, numberOfParameters, module, symbolTableIndex, false, takeName { name }) FunctionSymbol.Public(name.localHash.value, numberOfParameters, module, symbolTableIndex, false, bridgeTargetSymbol, takeName { name })
else else
FunctionSymbol.Private(privateFunIndex++, numberOfParameters, module, symbolTableIndex, false, takeName { name }) FunctionSymbol.Private(privateFunIndex++, numberOfParameters, module, symbolTableIndex, false, bridgeTargetSymbol, takeName { name })
} }
} }