diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt index b726a351b0c..ae6aa8c1ef3 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicEvaluator.kt @@ -11,20 +11,18 @@ import org.jetbrains.kotlin.ir.interpreter.IrInterpreterEnvironment import org.jetbrains.kotlin.ir.interpreter.fqName internal object IntrinsicEvaluator { + @OptIn(ExperimentalStdlibApi::class) + private val fqNameToHandler: Map = buildMap { + listOf( + EmptyArray, ArrayOf, ArrayOfNulls, ArrayConstructor, EnumValues, EnumValueOf, + JsPrimitives, SourceLocation, AssertIntrinsic, DataClassArrayToString + ).forEach { intrinsic -> intrinsic.getListOfAcceptableFunctions().forEach { put(it, intrinsic) } } + } + fun unwindInstructions(irFunction: IrFunction, environment: IrInterpreterEnvironment): List? { val fqName = irFunction.fqName - return when { - EmptyArray.canHandleFunctionWithName(fqName, irFunction.origin) -> EmptyArray.unwind(irFunction, environment) - ArrayOf.canHandleFunctionWithName(fqName, irFunction.origin) -> ArrayOf.unwind(irFunction, environment) - ArrayOfNulls.canHandleFunctionWithName(fqName, irFunction.origin) -> ArrayOfNulls.unwind(irFunction, environment) - EnumValues.canHandleFunctionWithName(fqName, irFunction.origin) -> EnumValues.unwind(irFunction, environment) - EnumValueOf.canHandleFunctionWithName(fqName, irFunction.origin) -> EnumValueOf.unwind(irFunction, environment) + return fqNameToHandler[fqName]?.unwind(irFunction, environment) ?: when { EnumIntrinsics.canHandleFunctionWithName(fqName, irFunction.origin) -> EnumIntrinsics.unwind(irFunction, environment) - JsPrimitives.canHandleFunctionWithName(fqName, irFunction.origin) -> JsPrimitives.unwind(irFunction, environment) - ArrayConstructor.canHandleFunctionWithName(fqName, irFunction.origin) -> ArrayConstructor.unwind(irFunction, environment) - SourceLocation.canHandleFunctionWithName(fqName, irFunction.origin) -> SourceLocation.unwind(irFunction, environment) - AssertIntrinsic.canHandleFunctionWithName(fqName, irFunction.origin) -> AssertIntrinsic.unwind(irFunction, environment) - DataClassArrayToString.canHandleFunctionWithName(fqName, irFunction.origin) -> DataClassArrayToString.unwind(irFunction, environment) else -> null } } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt index 129a877d42a..8b5ae74b64f 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/intrinsics/IntrinsicImplementations.kt @@ -23,7 +23,7 @@ import org.jetbrains.kotlin.types.Variance import java.util.* internal sealed class IntrinsicBase { - abstract fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean + abstract fun getListOfAcceptableFunctions(): List abstract fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) open fun unwind(irFunction: IrFunction, environment: IrInterpreterEnvironment): List { return listOf(customEvaluateInstruction(irFunction, environment)) @@ -38,8 +38,8 @@ internal sealed class IntrinsicBase { } internal object EmptyArray : IntrinsicBase() { - override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { - return fqName in setOf("kotlin.emptyArray", "kotlin.ArrayIntrinsicsKt.emptyArray") + override fun getListOfAcceptableFunctions(): List { + return listOf("kotlin.emptyArray", "kotlin.ArrayIntrinsicsKt.emptyArray") } override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { @@ -49,8 +49,11 @@ internal object EmptyArray : IntrinsicBase() { } internal object ArrayOf : IntrinsicBase() { - override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { - return fqName == "kotlin.arrayOf" || fqName.matches("kotlin\\.(byte|char|short|int|long|float|double|boolean|)ArrayOf".toRegex()) + override fun getListOfAcceptableFunctions(): List { + return listOf( + "kotlin.arrayOf", "kotlin.byteArrayOf", "kotlin.charArrayOf", "kotlin.shortArrayOf", "kotlin.intArrayOf", + "kotlin.longArrayOf", "kotlin.floatArrayOf", "kotlin.doubleArrayOf", "kotlin.booleanArrayOf" + ) } override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { @@ -61,8 +64,8 @@ internal object ArrayOf : IntrinsicBase() { } internal object ArrayOfNulls : IntrinsicBase() { - override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { - return fqName == "kotlin.arrayOfNulls" + override fun getListOfAcceptableFunctions(): List { + return listOf("kotlin.arrayOfNulls") } override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { @@ -78,8 +81,8 @@ internal object ArrayOfNulls : IntrinsicBase() { } internal object EnumValues : IntrinsicBase() { - override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { - return fqName == "kotlin.enumValues" + override fun getListOfAcceptableFunctions(): List { + return listOf("kotlin.enumValues") } private fun getEnumClass(irFunction: IrFunction, environment: IrInterpreterEnvironment): IrClass { @@ -108,8 +111,8 @@ internal object EnumValues : IntrinsicBase() { } internal object EnumValueOf : IntrinsicBase() { - override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { - return fqName == "kotlin.enumValueOf" + override fun getListOfAcceptableFunctions(): List { + return listOf("kotlin.enumValueOf") } private fun getEnumClass(irFunction: IrFunction, environment: IrInterpreterEnvironment): IrClass { @@ -144,7 +147,13 @@ internal object EnumValueOf : IntrinsicBase() { } internal object EnumIntrinsics : IntrinsicBase() { - override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { + override fun getListOfAcceptableFunctions(): List { + // functions that can be handled by this intrinsic cannot be described by single string + // must call instead `canHandleFunctionWithName` method + return listOf() + } + + fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { if (origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER) return true return fqName.startsWith("kotlin.Enum.") } @@ -188,8 +197,8 @@ internal object EnumIntrinsics : IntrinsicBase() { } internal object JsPrimitives : IntrinsicBase() { - override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { - return fqName == "kotlin.Long." || fqName == "kotlin.Char." + override fun getListOfAcceptableFunctions(): List { + return listOf("kotlin.Long.", "kotlin.Char.") } override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { @@ -208,8 +217,12 @@ internal object JsPrimitives : IntrinsicBase() { } internal object ArrayConstructor : IntrinsicBase() { - override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { - return fqName.matches("kotlin\\.(Byte|Char|Short|Int|Long|Float|Double|Boolean|)Array\\.".toRegex()) + override fun getListOfAcceptableFunctions(): List { + return listOf( + "kotlin.Array.", + "kotlin.ByteArray.", "kotlin.CharArray.", "kotlin.ShortArray.", "kotlin.IntArray.", + "kotlin.LongArray.", "kotlin.FloatArray.", "kotlin.DoubleArray.", "kotlin.BooleanArray." + ) } override fun unwind(irFunction: IrFunction, environment: IrInterpreterEnvironment): List { @@ -271,8 +284,8 @@ internal object ArrayConstructor : IntrinsicBase() { } internal object SourceLocation : IntrinsicBase() { - override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { - return fqName == "kotlin.experimental.sourceLocation" || fqName == "kotlin.experimental.SourceLocationKt.sourceLocation" + override fun getListOfAcceptableFunctions(): List { + return listOf("kotlin.experimental.sourceLocation", "kotlin.experimental.SourceLocationKt.sourceLocation") } override fun evaluate(irFunction: IrFunction, environment: IrInterpreterEnvironment) { @@ -281,8 +294,8 @@ internal object SourceLocation : IntrinsicBase() { } internal object AssertIntrinsic : IntrinsicBase() { - override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { - return fqName == "kotlin.PreconditionsKt.assert" + override fun getListOfAcceptableFunctions(): List { + return listOf("kotlin.PreconditionsKt.assert") } override fun unwind(irFunction: IrFunction, environment: IrInterpreterEnvironment): List { @@ -307,8 +320,8 @@ internal object AssertIntrinsic : IntrinsicBase() { } internal object DataClassArrayToString : IntrinsicBase() { - override fun canHandleFunctionWithName(fqName: String, origin: IrDeclarationOrigin): Boolean { - return fqName == "kotlin.internal.ir.dataClassArrayMemberToString" + override fun getListOfAcceptableFunctions(): List { + return listOf("kotlin.internal.ir.dataClassArrayMemberToString") } private fun arrayToString(array: Any?): String { diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt index 9b14f2805e2..6c952d83041 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/state/Wrapper.kt @@ -108,15 +108,10 @@ internal class Wrapper(val value: Any, override val irClass: IrClass, environmen "Array.kotlin.collections.copyToArrayOfAny(Boolean)" to "kotlin.collections.CollectionsKt", ) - private fun IrDeclarationWithName.getSignature(): String { + private fun IrFunction.getSignature(): String { val fqName = this.fqName - return when (this) { - is IrFunction -> { - val receiver = (dispatchReceiverParameter ?: extensionReceiverParameter)?.type?.getOnlyName()?.let { "$it." } ?: "" - this.valueParameters.joinToString(prefix = "$receiver$fqName(", postfix = ")") { it.type.getOnlyName() } - } - else -> fqName - } + val receiver = (dispatchReceiverParameter ?: extensionReceiverParameter)?.type?.getOnlyName()?.let { "$it." } ?: "" + return this.valueParameters.joinToString(prefix = "$receiver$fqName(", postfix = ")") { it.type.getOnlyName() } } private fun IrFunction.getJvmClassName(): String? { @@ -124,10 +119,9 @@ internal class Wrapper(val value: Any, override val irClass: IrClass, environmen } fun mustBeHandledWithWrapper(declaration: IrDeclarationWithName): Boolean { - val fqName = declaration.fqName return when (declaration) { is IrFunction -> declaration.getSignature() in intrinsicFunctionToHandler - else -> fqName in intrinsicClasses || fqName.startsWith("java") + else -> declaration.fqName.let { it in intrinsicClasses || it.startsWith("java") } } }