Added bridges building for workers

This commit is contained in:
Igor Chevdar
2017-12-05 17:21:16 +03:00
committed by Igor Chevdar
parent 9893951d9f
commit 8df6ff5215
2 changed files with 163 additions and 102 deletions
@@ -132,6 +132,7 @@ internal class KonanLower(val context: Context) {
}
phaser.phase(KonanPhase.BRIDGES_BUILDING) {
BridgesBuilding(context).runOnFilePostfix(irFile)
WorkersBridgesBuilding(context).lower(irFile)
}
phaser.phase(KonanPhase.AUTOBOX) {
validateIrFile(context, irFile)
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.backend.konan.lower
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.irBlockBody
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.builtins.KotlinBuiltIns
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.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrClass
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.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.expressions.*
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.util.createParameterDeclarations
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.util.type
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
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,
type: KotlinType,
returnValueOnFail: IrExpression)
= irIfThen(irNotIs(value, type), irReturn(returnValueOnFail))
val interop = context.interopBuiltIns
val symbols = context.ir.symbols
val nullableAnyType = context.builtIns.nullableAnyType
var runtimeJobDescriptor: FunctionDescriptor? = null
private fun IrBuilderWithScope.irConst(value: Any?) = when (value) {
null -> irNull()
is Int -> irInt(value)
is Boolean -> if (value) irTrue() else irFalse()
else -> TODO()
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
irDeclarationContainer.declarations.transformFlat {
listOf(it) + buildWorkerBridges(it)
}
}
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) {
val functions = mutableSetOf<FunctionDescriptor?>()
irClass.declarations.forEach {
@@ -74,108 +132,44 @@ internal class BridgesBuilding(val context: Context) : ClassLoweringPass {
functions.filterNotNull()
.filterNot { it.modality == Modality.ABSTRACT }
.forEach { function ->
function.allOverriddenDescriptors
.map { OverriddenFunctionDescriptor(function, it) }
.filter { !it.bridgeDirections.allNotNeeded() }
.filter { it.canBeCalledVirtually }
.filter { !it.inheritsBridge }
.distinctBy { it.bridgeDirections }
.forEach {
buildBridge(it, irClass)
builtBridges += it.descriptor
}
}
function.allOverriddenDescriptors
.map { OverriddenFunctionDescriptor(function, it) }
.filter { !it.bridgeDirections.allNotNeeded() }
.filter { it.canBeCalledVirtually }
.filter { !it.inheritsBridge }
.distinctBy { it.bridgeDirections }
.forEach {
buildBridge(it, irClass)
builtBridges += it.descriptor
}
}
irClass.transformChildrenVoid(object: IrElementTransformerVoid() {
override fun visitFunction(declaration: IrFunction): IrStatement {
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
?: 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)
declaration.body = irBuilder.irBlockBody(declaration) {
val valueParameters = declaration.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)
)
}
body.statements.forEach { +it }
}
buildTypeSafeBarrier(declaration, typeSafeBarrierDescription)
body.statements.forEach { +it }
}
return declaration
}
})
}
private object DECLARATION_ORIGIN_BRIDGE_METHOD :
IrDeclarationOriginImpl("BRIDGE_METHOD")
private fun buildBridge(descriptor: OverriddenFunctionDescriptor, irClass: IrClass) {
val bridgeDescriptor = context.specialDeclarationsFactory.getBridgeDescriptor(descriptor)
val bridge = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, DECLARATION_ORIGIN_BRIDGE_METHOD,
bridgeDescriptor).apply { createParameterDeclarations() }
val target = descriptor.descriptor
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() }
irClass.declarations.add(context.buildBridge(
startOffset = irClass.startOffset,
endOffset = irClass.endOffset,
descriptor = descriptor,
targetSymbol = irClass.findMember(descriptor.descriptor), // TODO: optimize.
superQualifierSymbol = irClass.symbol)
)
}
}
@@ -188,3 +182,69 @@ private fun IrClass.findMember(descriptor: FunctionDescriptor): IrFunctionSymbol
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
}