diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt index f437ac92e83..da729cb6b5c 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/BridgesConstruction.kt @@ -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() - .filter { !it.isStaticMethodOfClass } - .toList() - .forEach { generateBridges(it, irClass) } + override fun transformFlat(declaration: IrDeclaration): List? { + 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? { // 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() + 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