diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SpecialBridgeMethods.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SpecialBridgeMethods.kt index 355285f4ffd..262d18dc060 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SpecialBridgeMethods.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/lower/SpecialBridgeMethods.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.backend.common.lower import org.jetbrains.kotlin.backend.common.CommonBackendContext +import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.expressions.IrConstKind @@ -17,14 +18,16 @@ import org.jetbrains.kotlin.ir.util.parentAsClass import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name -data class SpecialMethodWithDefaultInfo(val defaultValueGenerator: (IrSimpleFunction) -> IrExpression, val argumentsToCheck: Int) +data class SpecialMethodWithDefaultInfo( + val defaultValueGenerator: (IrSimpleFunction) -> IrExpression, val argumentsToCheck: Int, val needsArgumentBoxing: Boolean = false +) class SpecialBridgeMethods(val context: CommonBackendContext) { private data class SpecialMethodDescription(val kotlinFqClassName: FqName?, val name: Name, val arity: Int) - private fun makeDescription(classFqName: String, funName: String, arity: Int) = + private fun makeDescription(classFqName: FqName, funName: String, arity: Int = 0) = SpecialMethodDescription( - FqName(classFqName), + classFqName, Name.identifier(funName), arity ) @@ -51,16 +54,36 @@ class SpecialBridgeMethods(val context: CommonBackendContext) { IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, bridge.valueParameters[1].symbol) private val SPECIAL_METHODS_WITH_DEFAULTS_MAP = mapOf( - makeDescription("kotlin.collections.Collection", "contains", 1) to SpecialMethodWithDefaultInfo(::constFalse, 1), - makeDescription("kotlin.collections.MutableCollection", "remove", 1) to SpecialMethodWithDefaultInfo(::constFalse, 1), - makeDescription("kotlin.collections.Map", "containsKey", 1) to SpecialMethodWithDefaultInfo(::constFalse, 1), - makeDescription("kotlin.collections.Map", "containsValue", 1) to SpecialMethodWithDefaultInfo(::constFalse, 1), - makeDescription("kotlin.collections.MutableMap", "remove", 2) to SpecialMethodWithDefaultInfo(::constFalse, 2), - makeDescription("kotlin.collections.Map", "getOrDefault", 2) to SpecialMethodWithDefaultInfo(::getSecondArg, 1), - makeDescription("kotlin.collections.Map", "get", 1) to SpecialMethodWithDefaultInfo(::constNull, 1), - makeDescription("kotlin.collections.MutableMap", "remove", 1) to SpecialMethodWithDefaultInfo(::constNull, 1), - makeDescription("kotlin.collections.List", "indexOf", 1) to SpecialMethodWithDefaultInfo(::constMinusOne, 1), - makeDescription("kotlin.collections.List", "lastIndexOf", 1) to SpecialMethodWithDefaultInfo(::constMinusOne, 1) + makeDescription(KotlinBuiltIns.FQ_NAMES.collection, "contains", 1) to SpecialMethodWithDefaultInfo(::constFalse, 1), + makeDescription(KotlinBuiltIns.FQ_NAMES.mutableCollection, "remove", 1) to SpecialMethodWithDefaultInfo(::constFalse, 1, true), + makeDescription(KotlinBuiltIns.FQ_NAMES.map, "containsKey", 1) to SpecialMethodWithDefaultInfo(::constFalse, 1), + makeDescription(KotlinBuiltIns.FQ_NAMES.map, "containsValue", 1) to SpecialMethodWithDefaultInfo(::constFalse, 1), + makeDescription(KotlinBuiltIns.FQ_NAMES.mutableMap, "remove", 2) to SpecialMethodWithDefaultInfo(::constFalse, 2), + makeDescription(KotlinBuiltIns.FQ_NAMES.map, "getOrDefault", 2) to SpecialMethodWithDefaultInfo(::getSecondArg, 1), + makeDescription(KotlinBuiltIns.FQ_NAMES.map, "get", 1) to SpecialMethodWithDefaultInfo(::constNull, 1), + makeDescription(KotlinBuiltIns.FQ_NAMES.mutableMap, "remove", 1) to SpecialMethodWithDefaultInfo(::constNull, 1), + makeDescription(KotlinBuiltIns.FQ_NAMES.list, "indexOf", 1) to SpecialMethodWithDefaultInfo(::constMinusOne, 1), + makeDescription(KotlinBuiltIns.FQ_NAMES.list, "lastIndexOf", 1) to SpecialMethodWithDefaultInfo(::constMinusOne, 1) + ) + + private val SPECIAL_PROPERTIES_SET = setOf( + makeDescription(KotlinBuiltIns.FQ_NAMES.collection, "size"), + makeDescription(KotlinBuiltIns.FQ_NAMES.map, "size"), + makeDescription(KotlinBuiltIns.FQ_NAMES.charSequence.toSafe(), "length"), + makeDescription(KotlinBuiltIns.FQ_NAMES.map, "keys"), + makeDescription(KotlinBuiltIns.FQ_NAMES.map, "values"), + makeDescription(KotlinBuiltIns.FQ_NAMES.map, "entries") + ) + + private val SPECIAL_METHODS_SETS = setOf( + makeDescription(KotlinBuiltIns.FQ_NAMES.number.toSafe(), "toByte"), + makeDescription(KotlinBuiltIns.FQ_NAMES.number.toSafe(), "toShort"), + makeDescription(KotlinBuiltIns.FQ_NAMES.number.toSafe(), "toInt"), + makeDescription(KotlinBuiltIns.FQ_NAMES.number.toSafe(), "toLong"), + makeDescription(KotlinBuiltIns.FQ_NAMES.number.toSafe(), "toFloat"), + makeDescription(KotlinBuiltIns.FQ_NAMES.number.toSafe(), "toDouble"), + makeDescription(KotlinBuiltIns.FQ_NAMES.mutableList, "removeAt", 1), + makeDescription(KotlinBuiltIns.FQ_NAMES.charSequence.toSafe(), "get", 1) ) fun findSpecialWithOverride(irFunction: IrSimpleFunction): Pair? { @@ -72,6 +95,22 @@ class SpecialBridgeMethods(val context: CommonBackendContext) { } return null } + + fun getSpecialMethodInfo(irFunction: IrSimpleFunction): SpecialMethodWithDefaultInfo? { + val description = irFunction.toDescription() + return SPECIAL_METHODS_WITH_DEFAULTS_MAP[description] + } + + fun isBuiltInWithDifferentJvmName(irFunction: IrSimpleFunction): Boolean { + irFunction.correspondingPropertySymbol?.let { + val classFqName = irFunction.parentAsClass.fqNameWhenAvailable + ?: return false + + return makeDescription(classFqName, it.owner.name.asString()) in SPECIAL_PROPERTIES_SET + } + + return irFunction.toDescription() in SPECIAL_METHODS_SETS + } } fun IrSimpleFunction.allOverridden(): Sequence {