Jvm Ir. IrIntrinsicMethods.kt optimization: avoid 'IrClass.functions' call if it not necessary

This commit is contained in:
Mikhael Bogdanov
2019-06-03 12:33:12 +02:00
parent 30ab11575d
commit bce774eda5
@@ -25,14 +25,12 @@ import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.declarations.IrValueParameter import org.jetbrains.kotlin.ir.declarations.IrValueParameter
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.classifierOrNull import org.jetbrains.kotlin.ir.types.classifierOrNull
import org.jetbrains.kotlin.ir.util.constructors
import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.properties
import org.jetbrains.kotlin.lexer.KtSingleValueToken import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -116,9 +114,9 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
unaryFunForPrimitives("dec", DEC) + unaryFunForPrimitives("dec", DEC) +
unaryFunForPrimitives("hashCode", HashCode) + unaryFunForPrimitives("hashCode", HashCode) +
unaryFunForPrimitives("toString", ToString) + unaryFunForPrimitives("toString", ToString) +
binaryFunForPrimitives("equals", EQUALS) + binaryFunForPrimitives("equals", EQUALS, irBuiltIns.anyClass) +
symbols.primitiveArrayOfByType.values.map { it.toKey() to ArrayOf } + symbols.primitiveArrayOfByType.values.map { it.toKey() to ArrayOf } +
binaryFunForPrimitives("rangeTo", RangeTo) + binaryFunForPrimitivesAcrossPrimitives("rangeTo", RangeTo) +
binaryOp("plus", IADD) + binaryOp("plus", IADD) +
binaryOp("minus", ISUB) + binaryOp("minus", ISUB) +
binaryOp("times", IMUL) + binaryOp("times", IMUL) +
@@ -131,11 +129,11 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
binaryOp("and", IAND) + binaryOp("and", IAND) +
binaryOp("or", IOR) + binaryOp("or", IOR) +
binaryOp("xor", IXOR) + binaryOp("xor", IXOR) +
binaryFunForPrimitives("compareTo", CompareTo) + binaryFunForPrimitivesAcrossPrimitives("compareTo", CompareTo) +
methodWithArity(irBuiltIns.booleanClass, "not", 0, Not) + createKeyMapping(Not, irBuiltIns.booleanClass, "not") +
methodWithArity(irBuiltIns.stringClass, "get", 1, StringGetChar) + createKeyMapping(StringGetChar, irBuiltIns.stringClass, "get", irBuiltIns.intClass) +
symbols.primitiveIteratorsByType.values.flatMap { iteratorClass -> symbols.primitiveIteratorsByType.values.map { iteratorClass ->
methodWithArity(iteratorClass, "next", 0, IteratorNext) createKeyMapping(IteratorNext, iteratorClass, "next")
} + } +
arrayMethods() + arrayMethods() +
primitiveComparisonIntrinsics(irBuiltIns.lessFunByOperandType, KtTokens.LT) + primitiveComparisonIntrinsics(irBuiltIns.lessFunByOperandType, KtTokens.LT) +
@@ -144,27 +142,60 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
primitiveComparisonIntrinsics(irBuiltIns.greaterOrEqualFunByOperandType, KtTokens.GTEQ) primitiveComparisonIntrinsics(irBuiltIns.greaterOrEqualFunByOperandType, KtTokens.GTEQ)
).toMap() ).toMap()
private val PrimitiveType.symbol
get() = irBuiltIns.primitiveTypeToIrType[this]!!.classOrNull!!
fun getIntrinsic(symbol: IrFunctionSymbol): IntrinsicMethod? = intrinsicsMap[symbol.toKey()] fun getIntrinsic(symbol: IrFunctionSymbol): IntrinsicMethod? = intrinsicsMap[symbol.toKey()]
private fun unaryFunForPrimitives(name: String, intrinsic: IntrinsicMethod): List<Pair<Key, IntrinsicMethod>> = private fun unaryFunForPrimitives(name: String, intrinsic: IntrinsicMethod): List<Pair<Key, IntrinsicMethod>> =
PrimitiveType.values().flatMap { type -> PrimitiveType.values().map { type ->
methodWithArity(irBuiltIns.primitiveTypeToIrType[type]!!.classOrNull!!, name, 0, intrinsic) createKeyMapping(intrinsic, type.symbol, name)
} }
private fun binaryFunForPrimitives(name: String, intrinsic: IntrinsicMethod): List<Pair<Key, IntrinsicMethod>> = private fun binaryFunForPrimitivesAcrossPrimitives(name: String, intrinsic: IntrinsicMethod): List<Pair<Key, IntrinsicMethod>> =
PrimitiveType.values().flatMap { type -> PrimitiveType.values().flatMap { parameter ->
methodWithArity(irBuiltIns.primitiveTypeToIrType[type]!!.classOrNull!!, name, 1, intrinsic) binaryFunForPrimitives(name, intrinsic, parameter.symbol)
} }
private fun binaryOp(methodName: String, opcode: Int) = binaryFunForPrimitives(methodName, BinaryOp(opcode))
private fun binaryFunForPrimitives(
name: String,
intrinsic: IntrinsicMethod,
parameter: IrClassifierSymbol
): List<Pair<Key, IntrinsicMethod>> =
PrimitiveType.values().map { type ->
createKeyMapping(
intrinsic,
type.symbol,
name,
parameter
)
}
private fun binaryOp(methodName: String, opcode: Int) = binaryFunForPrimitivesAcrossPrimitives(methodName, BinaryOp(opcode))
private fun numberConversionMethods(): List<Pair<Key, IntrinsicMethod>> = private fun numberConversionMethods(): List<Pair<Key, IntrinsicMethod>> =
PrimitiveType.NUMBER_TYPES.flatMap { type -> PrimitiveType.NUMBER_TYPES.flatMap { type ->
numberConversionMethods(irBuiltIns.primitiveTypeToIrType[type]!!.classOrNull!!) numberConversionMethods(type.symbol)
} + numberConversionMethods(irBuiltIns.numberClass) } + numberConversionMethods(irBuiltIns.numberClass)
private fun arrayMethods(): List<Pair<Key, IntrinsicMethod>> = private fun arrayMethods(): List<Pair<Key, IntrinsicMethod>> =
symbols.primitiveArrays.values.flatMap { arrayMethods(it) } + arrayMethods(symbols.array) symbols.primitiveArrays.flatMap { (key, value) ->
arrayMethods(
key.symbol,
value
)
} + arrayMethods(symbols.array.owner.typeParameters.single().symbol, symbols.array)
private fun arrayMethods(elementClass: IrClassifierSymbol, arrayClass: IrClassSymbol) =
listOf(
createKeyMapping(ArraySize, arrayClass, "<get-size>"),
createKeyMapping(NewArray, arrayClass, "<init>", irBuiltIns.intClass),
createKeyMapping(ArraySet, arrayClass, "set", irBuiltIns.intClass, elementClass),
createKeyMapping(ArrayGet, arrayClass, "get", irBuiltIns.intClass),
createKeyMapping(Clone, arrayClass, "clone"),
createKeyMapping(ArrayIterator, arrayClass, "iterator")
)
data class Key(val owner: FqName, val receiverParameterTypeName: FqName?, val name: String, val valueParameterTypeNames: List<FqName?>) data class Key(val owner: FqName, val receiverParameterTypeName: FqName?, val name: String, val valueParameterTypeNames: List<FqName?>)
@@ -186,7 +217,10 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
} }
private fun getParameterFqName(parameter: IrValueParameter?): FqName? = private fun getParameterFqName(parameter: IrValueParameter?): FqName? =
parameter?.type?.classifierOrNull?.owner?.let { getParameterFqName(parameter?.type?.classifierOrNull)
private fun getParameterFqName(parameter: IrClassifierSymbol?): FqName? =
parameter?.owner?.let {
when (it) { when (it) {
is IrClass -> it.fqNameWhenAvailable is IrClass -> it.fqNameWhenAvailable
is IrTypeParameter -> FqName(it.name.asString()) is IrTypeParameter -> FqName(it.name.asString())
@@ -194,26 +228,21 @@ class IrIntrinsicMethods(val irBuiltIns: IrBuiltIns, val symbols: JvmSymbols) {
} }
} }
private fun methodWithArity(klass: IrClassSymbol, name: String, arity: Int, intrinsic: IntrinsicMethod): List<Pair<Key, IntrinsicMethod>> = private fun createKeyMapping(
klass.owner.functions.filter { intrinsic: IntrinsicMethod,
it.name.asString() == name && it.valueParameters.size == arity klass: IrClassSymbol,
}.map { name: String,
it.symbol.toKey()!! to intrinsic vararg args: IrClassifierSymbol
}.toList() ): Pair<Key, IntrinsicMethod> =
Key(klass.owner.fqNameWhenAvailable!!, null, name, args.map {
getParameterFqName(it)
}) to intrinsic
private fun numberConversionMethods(numberClass: IrClassSymbol) = private fun numberConversionMethods(numberClass: IrClassSymbol) =
OperatorConventions.NUMBER_CONVERSIONS.flatMap { method -> OperatorConventions.NUMBER_CONVERSIONS.map { method ->
methodWithArity(numberClass, method.asString(), 0, NumberCast) createKeyMapping(NumberCast, numberClass, method.asString())
} }
private fun arrayMethods(arrayClass: IrClassSymbol) = listOf(
arrayClass.owner.properties.single { it.name.asString() == "size" }.getter!!.symbol.toKey()!! to ArraySize
) +
arrayClass.constructors.filter { it.owner.valueParameters.size == 1 }.map { it.toKey()!! to NewArray } +
methodWithArity(arrayClass, "set", 2, ArraySet) +
methodWithArity(arrayClass, "get", 1, ArrayGet) +
methodWithArity(arrayClass, "clone", 0, Clone) +
methodWithArity(arrayClass, "iterator", 0, ArrayIterator)
private fun primitiveComparisonIntrinsics(typeToIrFun: Map<SimpleType, IrSimpleFunctionSymbol>, operator: KtSingleValueToken) = private fun primitiveComparisonIntrinsics(typeToIrFun: Map<SimpleType, IrSimpleFunctionSymbol>, operator: KtSingleValueToken) =
typeToIrFun.map { (type, irFunSymbol) -> typeToIrFun.map { (type, irFunSymbol) ->