BridgesConstruction
This commit is contained in:
committed by
Anton Bannykh
parent
4142031fe7
commit
d9646a5361
+38
-33
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user