From 5f61f6f3a54f28e1a299ad7511f93eaf7f08e6f7 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Thu, 11 Jun 2020 00:50:22 +0300 Subject: [PATCH] Simplify interpretation for java methods with names other in kotlin --- .../backend/common/interpreter/Utils.kt | 4 +- .../common/interpreter/state/Wrapper.kt | 42 +++++++++++++++---- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt index 78597910444..36ab9e60194 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/Utils.kt @@ -246,7 +246,9 @@ fun getTypeArguments( container: IrTypeParametersContainer, expression: IrFunctionAccessExpression, mapper: (TypeParameterDescriptor) -> State ): List { return container.typeParameters.mapIndexed { index, typeParameter -> - val argumentState = expression.getTypeArgument(index)?.classOrNull?.owner?.let { Common(it) } ?: mapper(typeParameter.descriptor) + val typeArgument = expression.getTypeArgument(index)!! + val argumentState = typeArgument.classOrNull?.owner?.let { Common(it) } + ?: mapper(typeArgument.classifierOrFail.descriptor as TypeParameterDescriptor) Variable(typeParameter.descriptor, argumentState) } } diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Wrapper.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Wrapper.kt index 1a0aa8170b4..23287ce26d8 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Wrapper.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/state/Wrapper.kt @@ -12,8 +12,10 @@ import org.jetbrains.kotlin.backend.common.interpreter.getPrimitiveClass import org.jetbrains.kotlin.backend.common.interpreter.hasAnnotation import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap +import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.types.* @@ -21,7 +23,13 @@ import org.jetbrains.kotlin.ir.util.defaultType import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization import org.jetbrains.kotlin.ir.util.isTypeParameter import org.jetbrains.kotlin.ir.util.parentAsClass +import org.jetbrains.kotlin.load.java.BuiltinMethodsWithDifferentJvmName +import org.jetbrains.kotlin.load.java.BuiltinSpecialProperties import org.jetbrains.kotlin.name.FqNameUnsafe +import org.jetbrains.kotlin.resolve.descriptorUtil.firstOverridden +import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe +import org.jetbrains.kotlin.resolve.descriptorUtil.overriddenTreeAsSequence +import org.jetbrains.kotlin.resolve.descriptorUtil.propertyIfAccessor import java.lang.invoke.MethodHandle import java.lang.invoke.MethodHandles import java.lang.invoke.MethodType @@ -36,17 +44,14 @@ class Wrapper private constructor( constructor(value: Any, irClass: IrClass) : this(value, irClass, null) fun getMethod(irFunction: IrFunction): MethodHandle? { + if (irFunction.getEvaluateIntrinsicValue()?.isEmpty() == true) return null // this method will handle IntrinsicEvaluator // if function is actually a getter, then use "get${property.name.capitalize()}" as method name - val propertyName = (irFunction as? IrFunctionImpl)?.correspondingPropertySymbol?.owner?.name?.asString() - val propertyExplicitCall = propertyName?.takeIf { receiverClass.methods.map { it.name }.contains(it) } - val propertyGetCall = "get${propertyName?.capitalize()}".takeIf { receiverClass.methods.map { it.name }.contains(it) } - - // intrinsicName is used to get correct java method - // for example: - method 'get' in kotlin StringBuilder is actually 'charAt' in java StringBuilder - val intrinsicName = irFunction.getEvaluateIntrinsicValue() - if (intrinsicName?.isEmpty() == true) return null - val methodName = intrinsicName ?: propertyExplicitCall ?: propertyGetCall ?: irFunction.name.toString() + val propertyName = (irFunction as? IrSimpleFunction)?.correspondingPropertySymbol?.owner?.name?.asString() + val propertyCall = listOfNotNull(propertyName, "get${propertyName?.capitalize()}") + .firstOrNull { receiverClass.methods.any { method -> method.name == it } } + val intrinsicName = getJavaOriginalName(irFunction) + val methodName = intrinsicName ?: propertyCall ?: irFunction.name.toString() val methodType = irFunction.getMethodType() return MethodHandles.lookup().findVirtual(receiverClass, methodName, methodType) } @@ -55,6 +60,25 @@ class Wrapper private constructor( throw UnsupportedOperationException("Method setState is not supported in Wrapper class") } + // this method is used to get correct java method name + // for example: - method 'get' in kotlin StringBuilder is actually 'charAt' in java StringBuilder + // - method 'keys' in kotlin Map is actually 'keySet' in java + private fun getJavaOriginalName(irFunction: IrFunction): String? { + return when { + (irFunction as? IrSimpleFunction)?.correspondingPropertySymbol != null -> { + val property = irFunction.descriptor.firstOverridden { + BuiltinSpecialProperties.hasBuiltinSpecialPropertyFqName(it.propertyIfAccessor) + } + property?.let { BuiltinSpecialProperties.PROPERTY_FQ_NAME_TO_JVM_GETTER_NAME_MAP[it.propertyIfAccessor.fqNameSafe]?.asString() } + } + irFunction.descriptor is SimpleFunctionDescriptor -> { + val last = irFunction.descriptor.overriddenTreeAsSequence(true).last() + BuiltinMethodsWithDifferentJvmName.getJvmName(last as SimpleFunctionDescriptor)?.asString() + } + else -> null + } + } + companion object { private val companionObjectValue = mapOf("kotlin.text.Regex\$Companion" to Regex.Companion)