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
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
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.generateBridges
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.lower.*
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.ir.JsIrBuilder
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.impl.IrValueParameterImpl
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.classifierOrNull
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
// }
//
class BridgesConstruction(val context: CommonBackendContext) : ClassLoweringPass {
class BridgesConstruction(val context: CommonBackendContext) : DeclarationTransformer {
private val specialBridgeMethods = SpecialBridgeMethods(context)
override fun lower(irClass: IrClass) {
irClass.declarations
.asSequence()
.filterIsInstance<IrSimpleFunction>()
.filter { !it.isStaticMethodOfClass }
.toList()
.forEach { generateBridges(it, irClass) }
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
if (declaration !is IrSimpleFunction || declaration.isStaticMethodOfClass || declaration.parent !is IrClass) return null
return generateBridges(declaration)?.let { listOf(declaration) + it }
}
private fun generateBridges(function: IrSimpleFunction, irClass: IrClass) {
private fun generateBridges(function: IrSimpleFunction): List<IrDeclaration>? {
// equals(Any?), hashCode(), toString() never need bridges
if (function.isMethodOfAny())
return
return null
val (specialOverride: IrSimpleFunction?, specialOverrideInfo) =
specialBridgeMethods.findSpecialWithOverride(function) ?: Pair(null, null)
@@ -74,6 +73,10 @@ class BridgesConstruction(val context: CommonBackendContext) : ClassLoweringPass
signature = { FunctionAndSignature(it.function) }
)
if (bridgesToGenerate.isEmpty()) return null
val result = mutableListOf<IrDeclaration>()
for ((from, to) in bridgesToGenerate) {
if (!from.function.parentAsClass.isInterface &&
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
@@ -141,32 +146,32 @@ class BridgesConstruction(val context: CommonBackendContext) : ClassLoweringPass
overriddenSymbols += bridge.symbol
}
context.createIrBuilder(irFunction.symbol).irBlockBody(irFunction) {
if (specialMethodInfo != null) {
irFunction.valueParameters.take(specialMethodInfo.argumentsToCheck).forEach {
+irIfThen(
context.irBuiltIns.unitType,
irNot(irIs(irGet(it), delegateTo.valueParameters[it.index].type)),
irReturn(specialMethodInfo.defaultValueGenerator(irFunction))
)
irFunction.body = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
statements += context.createIrBuilder(irFunction.symbol).irBlockBody(irFunction) {
if (specialMethodInfo != null) {
irFunction.valueParameters.take(specialMethodInfo.argumentsToCheck).forEach {
+irIfThen(
context.irBuiltIns.unitType,
irNot(irIs(irGet(it), delegateTo.valueParameters[it.index].type)),
irReturn(specialMethodInfo.defaultValueGenerator(irFunction))
)
}
}
}
val call = irCall(delegateTo.symbol)
call.dispatchReceiver = irGet(irFunction.dispatchReceiverParameter!!)
irFunction.extensionReceiverParameter?.let {
call.extensionReceiver = irCastIfNeeded(irGet(it), delegateTo.extensionReceiverParameter!!.type)
}
val call = irCall(delegateTo.symbol)
call.dispatchReceiver = irGet(irFunction.dispatchReceiverParameter!!)
irFunction.extensionReceiverParameter?.let {
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 ->
call.putValueArgument(i, irCastIfNeeded(irGet(valueParameter), delegateTo.valueParameters[i].type))
}
irFunction.valueParameters.subList(0, toTake).mapIndexed { i, valueParameter ->
call.putValueArgument(i, irCastIfNeeded(irGet(valueParameter), delegateTo.valueParameters[i].type))
}
+irReturn(call)
}.apply {
irFunction.body = this
+irReturn(call)
}.statements
}
return irFunction