BridgesConstruction

This commit is contained in:
Anton Bannykh
2019-12-24 20:52:11 +03:00
committed by Anton Bannykh
parent 4142031fe7
commit d9646a5361
@@ -5,8 +5,8 @@
package org.jetbrains.kotlin.ir.backend.js.lower package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
import org.jetbrains.kotlin.backend.common.CommonBackendContext import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.bridges.FunctionHandle import org.jetbrains.kotlin.backend.common.bridges.FunctionHandle
import org.jetbrains.kotlin.backend.common.bridges.generateBridges import org.jetbrains.kotlin.backend.common.bridges.generateBridges
import org.jetbrains.kotlin.backend.common.ir.copyTo import org.jetbrains.kotlin.backend.common.ir.copyTo
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
import org.jetbrains.kotlin.backend.common.ir.isSuspend import org.jetbrains.kotlin.backend.common.ir.isSuspend
import org.jetbrains.kotlin.backend.common.lower.* import org.jetbrains.kotlin.backend.common.lower.*
import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.backend.js.utils.functionSignature import org.jetbrains.kotlin.ir.backend.js.utils.functionSignature
@@ -23,6 +24,7 @@ import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
@@ -46,23 +48,20 @@ import org.jetbrains.kotlin.ir.util.*
// fun foo(t: Any?) = foo(t as Int) // Constructed bridge // fun foo(t: Any?) = foo(t as Int) // Constructed bridge
// } // }
// //
class BridgesConstruction(val context: CommonBackendContext) : ClassLoweringPass { class BridgesConstruction(val context: CommonBackendContext) : DeclarationTransformer {
private val specialBridgeMethods = SpecialBridgeMethods(context) private val specialBridgeMethods = SpecialBridgeMethods(context)
override fun lower(irClass: IrClass) { override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
irClass.declarations if (declaration !is IrSimpleFunction || declaration.isStaticMethodOfClass || declaration.parent !is IrClass) return null
.asSequence()
.filterIsInstance<IrSimpleFunction>() return generateBridges(declaration)?.let { listOf(declaration) + it }
.filter { !it.isStaticMethodOfClass }
.toList()
.forEach { generateBridges(it, irClass) }
} }
private fun generateBridges(function: IrSimpleFunction, irClass: IrClass) { private fun generateBridges(function: IrSimpleFunction): List<IrDeclaration>? {
// equals(Any?), hashCode(), toString() never need bridges // equals(Any?), hashCode(), toString() never need bridges
if (function.isMethodOfAny()) if (function.isMethodOfAny())
return return null
val (specialOverride: IrSimpleFunction?, specialOverrideInfo) = val (specialOverride: IrSimpleFunction?, specialOverrideInfo) =
specialBridgeMethods.findSpecialWithOverride(function) ?: Pair(null, null) specialBridgeMethods.findSpecialWithOverride(function) ?: Pair(null, null)
@@ -74,6 +73,10 @@ class BridgesConstruction(val context: CommonBackendContext) : ClassLoweringPass
signature = { FunctionAndSignature(it.function) } signature = { FunctionAndSignature(it.function) }
) )
if (bridgesToGenerate.isEmpty()) return null
val result = mutableListOf<IrDeclaration>()
for ((from, to) in bridgesToGenerate) { for ((from, to) in bridgesToGenerate) {
if (!from.function.parentAsClass.isInterface && if (!from.function.parentAsClass.isInterface &&
from.function.isReal && from.function.isReal &&
@@ -97,8 +100,10 @@ class BridgesConstruction(val context: CommonBackendContext) : ClassLoweringPass
} }
irClass.declarations.add(bridge) result += bridge
} }
return result
} }
// Ported from from jvm.lower.BridgeLowering // Ported from from jvm.lower.BridgeLowering
@@ -141,32 +146,32 @@ class BridgesConstruction(val context: CommonBackendContext) : ClassLoweringPass
overriddenSymbols += bridge.symbol overriddenSymbols += bridge.symbol
} }
context.createIrBuilder(irFunction.symbol).irBlockBody(irFunction) { irFunction.body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
if (specialMethodInfo != null) { statements += context.createIrBuilder(irFunction.symbol).irBlockBody(irFunction) {
irFunction.valueParameters.take(specialMethodInfo.argumentsToCheck).forEach { if (specialMethodInfo != null) {
+irIfThen( irFunction.valueParameters.take(specialMethodInfo.argumentsToCheck).forEach {
context.irBuiltIns.unitType, +irIfThen(
irNot(irIs(irGet(it), delegateTo.valueParameters[it.index].type)), context.irBuiltIns.unitType,
irReturn(specialMethodInfo.defaultValueGenerator(irFunction)) irNot(irIs(irGet(it), delegateTo.valueParameters[it.index].type)),
) irReturn(specialMethodInfo.defaultValueGenerator(irFunction))
)
}
} }
}
val call = irCall(delegateTo.symbol) val call = irCall(delegateTo.symbol)
call.dispatchReceiver = irGet(irFunction.dispatchReceiverParameter!!) call.dispatchReceiver = irGet(irFunction.dispatchReceiverParameter!!)
irFunction.extensionReceiverParameter?.let { irFunction.extensionReceiverParameter?.let {
call.extensionReceiver = irCastIfNeeded(irGet(it), delegateTo.extensionReceiverParameter!!.type) call.extensionReceiver = irCastIfNeeded(irGet(it), delegateTo.extensionReceiverParameter!!.type)
} }
val toTake = irFunction.valueParameters.size - if (call.isSuspend xor irFunction.isSuspend) 1 else 0 val toTake = irFunction.valueParameters.size - if (call.isSuspend xor irFunction.isSuspend) 1 else 0
irFunction.valueParameters.subList(0, toTake).mapIndexed { i, valueParameter -> irFunction.valueParameters.subList(0, toTake).mapIndexed { i, valueParameter ->
call.putValueArgument(i, irCastIfNeeded(irGet(valueParameter), delegateTo.valueParameters[i].type)) call.putValueArgument(i, irCastIfNeeded(irGet(valueParameter), delegateTo.valueParameters[i].type))
} }
+irReturn(call) +irReturn(call)
}.apply { }.statements
irFunction.body = this
} }
return irFunction return irFunction