Added bridges building for workers
This commit is contained in:
committed by
Igor Chevdar
parent
9893951d9f
commit
8df6ff5215
+1
@@ -132,6 +132,7 @@ internal class KonanLower(val context: Context) {
|
|||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.BRIDGES_BUILDING) {
|
phaser.phase(KonanPhase.BRIDGES_BUILDING) {
|
||||||
BridgesBuilding(context).runOnFilePostfix(irFile)
|
BridgesBuilding(context).runOnFilePostfix(irFile)
|
||||||
|
WorkersBridgesBuilding(context).lower(irFile)
|
||||||
}
|
}
|
||||||
phaser.phase(KonanPhase.AUTOBOX) {
|
phaser.phase(KonanPhase.AUTOBOX) {
|
||||||
validateIrFile(context, irFile)
|
validateIrFile(context, irFile)
|
||||||
|
|||||||
+162
-102
@@ -17,6 +17,7 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.lower
|
package org.jetbrains.kotlin.backend.konan.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||||
|
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
|
||||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
||||||
@@ -24,38 +25,95 @@ import org.jetbrains.kotlin.backend.konan.Context
|
|||||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
|
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||||
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
import org.jetbrains.kotlin.ir.util.type
|
import org.jetbrains.kotlin.ir.util.type
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
internal class WorkersBridgesBuilding(val context: Context) : DeclarationContainerLoweringPass, IrElementTransformerVoid() {
|
||||||
|
|
||||||
private fun IrBuilderWithScope.returnIfBadType(value: IrExpression,
|
val interop = context.interopBuiltIns
|
||||||
type: KotlinType,
|
val symbols = context.ir.symbols
|
||||||
returnValueOnFail: IrExpression)
|
val nullableAnyType = context.builtIns.nullableAnyType
|
||||||
= irIfThen(irNotIs(value, type), irReturn(returnValueOnFail))
|
var runtimeJobDescriptor: FunctionDescriptor? = null
|
||||||
|
|
||||||
private fun IrBuilderWithScope.irConst(value: Any?) = when (value) {
|
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||||
null -> irNull()
|
irDeclarationContainer.declarations.transformFlat {
|
||||||
is Int -> irInt(value)
|
listOf(it) + buildWorkerBridges(it)
|
||||||
is Boolean -> if (value) irTrue() else irFalse()
|
}
|
||||||
else -> TODO()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun buildWorkerBridges(declaration: IrDeclaration): List<IrFunction> {
|
||||||
|
val bridges = mutableListOf<IrFunction>()
|
||||||
|
declaration.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||||
|
|
||||||
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
|
||||||
|
val descriptor = expression.descriptor.original
|
||||||
|
if (descriptor != interop.scheduleImplFunction)
|
||||||
|
return expression
|
||||||
|
|
||||||
|
val job = expression.getValueArgument(3) as IrFunctionReference
|
||||||
|
val jobDescriptor = job.descriptor
|
||||||
|
val arg = jobDescriptor.valueParameters[0]
|
||||||
|
if (runtimeJobDescriptor == null) {
|
||||||
|
runtimeJobDescriptor = jobDescriptor.newCopyBuilder()
|
||||||
|
.setReturnType(nullableAnyType)
|
||||||
|
.setValueParameters(listOf(ValueParameterDescriptorImpl(
|
||||||
|
containingDeclaration = jobDescriptor,
|
||||||
|
original = null,
|
||||||
|
index = 0,
|
||||||
|
annotations = Annotations.EMPTY,
|
||||||
|
name = arg.name,
|
||||||
|
outType = nullableAnyType,
|
||||||
|
declaresDefaultValue = arg.declaresDefaultValue(),
|
||||||
|
isCrossinline = arg.isCrossinline,
|
||||||
|
isNoinline = arg.isNoinline,
|
||||||
|
varargElementType = arg.varargElementType,
|
||||||
|
source = arg.source
|
||||||
|
)))
|
||||||
|
.build()!!
|
||||||
|
}
|
||||||
|
val overriddenJobDescriptor = OverriddenFunctionDescriptor(jobDescriptor, runtimeJobDescriptor!!)
|
||||||
|
if (!overriddenJobDescriptor.needBridge) return expression
|
||||||
|
|
||||||
|
val bridge = context.buildBridge(
|
||||||
|
startOffset = job.startOffset,
|
||||||
|
endOffset = job.endOffset,
|
||||||
|
descriptor = overriddenJobDescriptor,
|
||||||
|
targetSymbol = job.symbol)
|
||||||
|
bridges += bridge
|
||||||
|
expression.putValueArgument(3, IrFunctionReferenceImpl(
|
||||||
|
startOffset = job.startOffset,
|
||||||
|
endOffset = job.endOffset,
|
||||||
|
type = job.type,
|
||||||
|
symbol = bridge.symbol,
|
||||||
|
descriptor = bridge.descriptor,
|
||||||
|
typeArguments = null)
|
||||||
|
)
|
||||||
|
return expression
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return bridges
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
||||||
|
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
val functions = mutableSetOf<FunctionDescriptor?>()
|
val functions = mutableSetOf<FunctionDescriptor?>()
|
||||||
irClass.declarations.forEach {
|
irClass.declarations.forEach {
|
||||||
@@ -74,108 +132,44 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
|
|||||||
functions.filterNotNull()
|
functions.filterNotNull()
|
||||||
.filterNot { it.modality == Modality.ABSTRACT }
|
.filterNot { it.modality == Modality.ABSTRACT }
|
||||||
.forEach { function ->
|
.forEach { function ->
|
||||||
function.allOverriddenDescriptors
|
function.allOverriddenDescriptors
|
||||||
.map { OverriddenFunctionDescriptor(function, it) }
|
.map { OverriddenFunctionDescriptor(function, it) }
|
||||||
.filter { !it.bridgeDirections.allNotNeeded() }
|
.filter { !it.bridgeDirections.allNotNeeded() }
|
||||||
.filter { it.canBeCalledVirtually }
|
.filter { it.canBeCalledVirtually }
|
||||||
.filter { !it.inheritsBridge }
|
.filter { !it.inheritsBridge }
|
||||||
.distinctBy { it.bridgeDirections }
|
.distinctBy { it.bridgeDirections }
|
||||||
.forEach {
|
.forEach {
|
||||||
buildBridge(it, irClass)
|
buildBridge(it, irClass)
|
||||||
builtBridges += it.descriptor
|
builtBridges += it.descriptor
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
irClass.transformChildrenVoid(object: IrElementTransformerVoid() {
|
irClass.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||||
override fun visitFunction(declaration: IrFunction): IrStatement {
|
override fun visitFunction(declaration: IrFunction): IrStatement {
|
||||||
declaration.transformChildrenVoid(this)
|
declaration.transformChildrenVoid(this)
|
||||||
|
|
||||||
val descriptor = declaration.descriptor
|
|
||||||
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor)
|
|
||||||
if (typeSafeBarrierDescription == null || builtBridges.contains(descriptor))
|
|
||||||
return declaration
|
|
||||||
|
|
||||||
val body = declaration.body as? IrBlockBody
|
val body = declaration.body as? IrBlockBody
|
||||||
?: return declaration
|
?: return declaration
|
||||||
|
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(declaration.descriptor)
|
||||||
|
if (typeSafeBarrierDescription == null || builtBridges.contains(declaration.descriptor))
|
||||||
|
return declaration
|
||||||
|
|
||||||
val irBuilder = context.createIrBuilder(declaration.symbol, declaration.startOffset, declaration.endOffset)
|
val irBuilder = context.createIrBuilder(declaration.symbol, declaration.startOffset, declaration.endOffset)
|
||||||
declaration.body = irBuilder.irBlockBody(declaration) {
|
declaration.body = irBuilder.irBlockBody(declaration) {
|
||||||
val valueParameters = declaration.valueParameters
|
buildTypeSafeBarrier(declaration, typeSafeBarrierDescription)
|
||||||
for (i in valueParameters.indices) {
|
body.statements.forEach { +it }
|
||||||
if (!typeSafeBarrierDescription.checkParameter(i))
|
|
||||||
continue
|
|
||||||
val type = valueParameters[i].type
|
|
||||||
if (type != context.builtIns.nullableAnyType) {
|
|
||||||
+returnIfBadType(irGet(valueParameters[i].symbol), type,
|
|
||||||
if (typeSafeBarrierDescription == BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT)
|
|
||||||
irGet(valueParameters[2].symbol)
|
|
||||||
else irConst(typeSafeBarrierDescription.defaultValue)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
body.statements.forEach { +it }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return declaration
|
return declaration
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private object DECLARATION_ORIGIN_BRIDGE_METHOD :
|
|
||||||
IrDeclarationOriginImpl("BRIDGE_METHOD")
|
|
||||||
|
|
||||||
private fun buildBridge(descriptor: OverriddenFunctionDescriptor, irClass: IrClass) {
|
private fun buildBridge(descriptor: OverriddenFunctionDescriptor, irClass: IrClass) {
|
||||||
val bridgeDescriptor = context.specialDeclarationsFactory.getBridgeDescriptor(descriptor)
|
irClass.declarations.add(context.buildBridge(
|
||||||
val bridge = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, DECLARATION_ORIGIN_BRIDGE_METHOD,
|
startOffset = irClass.startOffset,
|
||||||
bridgeDescriptor).apply { createParameterDeclarations() }
|
endOffset = irClass.endOffset,
|
||||||
|
descriptor = descriptor,
|
||||||
val target = descriptor.descriptor
|
targetSymbol = irClass.findMember(descriptor.descriptor), // TODO: optimize.
|
||||||
|
superQualifierSymbol = irClass.symbol)
|
||||||
assert(target.containingDeclaration == irClass.descriptor)
|
|
||||||
val superQualifierSymbol = irClass.symbol
|
|
||||||
val targetSymbol = irClass.findMember(target) // TODO: optimize
|
|
||||||
|
|
||||||
val statements = mutableListOf<IrExpression>()
|
|
||||||
val irBuilder = context.createIrBuilder(bridge.symbol, irClass.startOffset, irClass.endOffset)
|
|
||||||
irBuilder.run {
|
|
||||||
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor)
|
|
||||||
if (typeSafeBarrierDescription != null) {
|
|
||||||
val valueParameters = bridge.valueParameters
|
|
||||||
for (i in valueParameters.indices) {
|
|
||||||
if (!typeSafeBarrierDescription.checkParameter(i))
|
|
||||||
continue
|
|
||||||
val type = target.valueParameters[i].type
|
|
||||||
if (type != context.builtIns.nullableAnyType) {
|
|
||||||
statements += returnIfBadType(irGet(valueParameters[i].symbol), type,
|
|
||||||
if (typeSafeBarrierDescription == BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT)
|
|
||||||
irGet(valueParameters[2].symbol)
|
|
||||||
else irConst(typeSafeBarrierDescription.defaultValue)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val delegatingCall = IrCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetSymbol, target,
|
|
||||||
superQualifierSymbol = superQualifierSymbol /* Call non-virtually */
|
|
||||||
).apply {
|
|
||||||
val dispatchReceiverParameter = bridge.dispatchReceiverParameter
|
|
||||||
if (dispatchReceiverParameter != null)
|
|
||||||
dispatchReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, dispatchReceiverParameter.symbol)
|
|
||||||
val extensionReceiverParameter = bridge.extensionReceiverParameter
|
|
||||||
if (extensionReceiverParameter != null)
|
|
||||||
extensionReceiver = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, extensionReceiverParameter.symbol)
|
|
||||||
bridge.valueParameters.forEachIndexed { index, parameter ->
|
|
||||||
this.putValueArgument(index, IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter.symbol))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val bridgeBody = if (bridgeDescriptor.returnType.let { it != null && !KotlinBuiltIns.isUnitOrNullableUnit(it) })
|
|
||||||
IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, bridge.symbol, delegatingCall)
|
|
||||||
else
|
|
||||||
delegatingCall
|
|
||||||
statements += bridgeBody
|
|
||||||
irClass.declarations.add(
|
|
||||||
IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, DECLARATION_ORIGIN_BRIDGE_METHOD,
|
|
||||||
bridgeDescriptor, IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, statements)
|
|
||||||
).apply { createParameterDeclarations() }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -188,3 +182,69 @@ private fun IrClass.findMember(descriptor: FunctionDescriptor): IrFunctionSymbol
|
|||||||
|
|
||||||
return (functions + propertyAccessors).single { it.descriptor == descriptor }
|
return (functions + propertyAccessors).single { it.descriptor == descriptor }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object DECLARATION_ORIGIN_BRIDGE_METHOD :
|
||||||
|
IrDeclarationOriginImpl("BRIDGE_METHOD")
|
||||||
|
|
||||||
|
private fun IrBuilderWithScope.returnIfBadType(value: IrExpression,
|
||||||
|
type: KotlinType,
|
||||||
|
returnValueOnFail: IrExpression)
|
||||||
|
= irIfThen(irNotIs(value, type), irReturn(returnValueOnFail))
|
||||||
|
|
||||||
|
private fun IrBuilderWithScope.irConst(value: Any?) = when (value) {
|
||||||
|
null -> irNull()
|
||||||
|
is Int -> irInt(value)
|
||||||
|
is Boolean -> if (value) irTrue() else irFalse()
|
||||||
|
else -> TODO()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun IrBlockBodyBuilder.buildTypeSafeBarrier(function: IrFunction,
|
||||||
|
typeSafeBarrierDescription: BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription) {
|
||||||
|
val valueParameters = function.valueParameters
|
||||||
|
for (i in valueParameters.indices) {
|
||||||
|
if (!typeSafeBarrierDescription.checkParameter(i))
|
||||||
|
continue
|
||||||
|
val type = valueParameters[i].type
|
||||||
|
if (type != context.builtIns.nullableAnyType) {
|
||||||
|
+returnIfBadType(irGet(valueParameters[i].symbol), type,
|
||||||
|
if (typeSafeBarrierDescription == BuiltinMethodsWithSpecialGenericSignature.TypeSafeBarrierDescription.MAP_GET_OR_DEFAULT)
|
||||||
|
irGet(valueParameters[2].symbol)
|
||||||
|
else irConst(typeSafeBarrierDescription.defaultValue)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Context.buildBridge(startOffset: Int, endOffset: Int,
|
||||||
|
descriptor: OverriddenFunctionDescriptor, targetSymbol: IrFunctionSymbol,
|
||||||
|
superQualifierSymbol: IrClassSymbol? = null): IrFunctionImpl {
|
||||||
|
val bridgeDescriptor = specialDeclarationsFactory.getBridgeDescriptor(descriptor)
|
||||||
|
val bridge = IrFunctionImpl(startOffset, endOffset, DECLARATION_ORIGIN_BRIDGE_METHOD,
|
||||||
|
bridgeDescriptor).apply { createParameterDeclarations() }
|
||||||
|
|
||||||
|
val irBuilder = createIrBuilder(bridge.symbol, startOffset, endOffset)
|
||||||
|
bridge.body = irBuilder.irBlockBody(bridge) {
|
||||||
|
val typeSafeBarrierDescription = BuiltinMethodsWithSpecialGenericSignature.getDefaultValueForOverriddenBuiltinFunction(descriptor.overriddenDescriptor)
|
||||||
|
typeSafeBarrierDescription?.let { buildTypeSafeBarrier(bridge, it) }
|
||||||
|
|
||||||
|
val delegatingCall = IrCallImpl(startOffset, endOffset, targetSymbol, descriptor.descriptor,
|
||||||
|
superQualifierSymbol = superQualifierSymbol /* Call non-virtually */
|
||||||
|
).apply {
|
||||||
|
bridge.dispatchReceiverParameter?.let {
|
||||||
|
dispatchReceiver = irGet(it.symbol)
|
||||||
|
}
|
||||||
|
bridge.extensionReceiverParameter?.let {
|
||||||
|
extensionReceiver = irGet(it.symbol)
|
||||||
|
}
|
||||||
|
bridge.valueParameters.forEachIndexed { index, parameter ->
|
||||||
|
this.putValueArgument(index, irGet(parameter.symbol))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (KotlinBuiltIns.isUnitOrNullableUnit(bridgeDescriptor.returnType!!))
|
||||||
|
+delegatingCall
|
||||||
|
else
|
||||||
|
+irReturn(delegatingCall)
|
||||||
|
}
|
||||||
|
return bridge
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user