From 792ae8d272f38ac7c8dfed7d2077814bb6a1cae9 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Wed, 10 Jun 2020 19:22:57 +0300 Subject: [PATCH] Get rid of dynamic cast interpretation --- .../common/interpreter/IrInterpreter.kt | 18 +++++++++++++++--- .../kotlin/backend/common/interpreter/Utils.kt | 7 +++++-- .../intrinsic/InterpreterIntrinsics.kt | 12 ++++++++++++ .../backend/common/interpreter/stack/State.kt | 6 ++---- 4 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/intrinsic/InterpreterIntrinsics.kt diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt index 244b7f6b81e..ff8fbe9f3cb 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/IrInterpreter.kt @@ -355,6 +355,20 @@ class IrInterpreter(irModule: IrModuleFragment) { data.pushReturnValue(Lambda(irLambdaFunction.symbol.owner, irLambdaFunction.type.classOrNull!!.owner)) return Code.NEXT } + + val inlineFunOwner = (block as? IrReturnableBlock)?.inlineFunctionSymbol?.owner + if (inlineFunOwner?.hasAnnotation(evaluateIntrinsicAnnotation) == true) { + val rawArgs = block.statements.filterIsInstance().zip(inlineFunOwner.valueParameters) + val args = mutableListOf() + for ((variable, valueParameter) in rawArgs) { + val tempFrame = data.copy().apply { variable.initializer!!.interpret(this).also { if (it != Code.NEXT) return it } } + // must set variable descriptor here because temp variables inside ir returnable block have different from methods args names + args += Variable(valueParameter.descriptor, tempFrame.popReturnValue()) + } + val newFrame = data.copy().apply { addAll(args) } + return Wrapper.getStaticMethod(inlineFunOwner).invokeMethod(inlineFunOwner, newFrame).apply { data.pushReturnValue(newFrame) } + } + return interpretStatements(block.statements, data) } @@ -466,9 +480,7 @@ class IrInterpreter(irModule: IrModuleFragment) { private fun interpretTypeOperatorCall(expression: IrTypeOperatorCall, data: Frame): Code { return when (expression.operator) { - IrTypeOperator.IMPLICIT_COERCION_TO_UNIT, IrTypeOperator.IMPLICIT_DYNAMIC_CAST -> { - expression.argument.interpret(data) - } + IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> expression.argument.interpret(data) IrTypeOperator.CAST, IrTypeOperator.IMPLICIT_CAST -> { val code = expression.argument.interpret(data) if (!data.peekReturnValue().irClass.defaultType.isSubtypeOf(expression.type, irBuiltIns)) { 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 8713ac5382f..91f38197c8f 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 @@ -106,7 +106,8 @@ fun State.toIrExpression(expression: IrExpression): IrExpression { fun Any?.toState(irType: IrType): State { return when (this) { is State -> this - is Boolean, is Char, is Byte, is Short, is Int, is Long, is String, is Float, is Double -> Primitive(this, irType) + is Boolean, is Char, is Byte, is Short, is Int, is Long, is String, is Float, is Double, is Array<*>, is ByteArray, + is CharArray, is ShortArray, is IntArray, is LongArray, is FloatArray, is DoubleArray, is BooleanArray -> Primitive(this, irType) null -> Primitive(this, irType) else -> Wrapper(this, irType.classOrNull!!.owner) } @@ -145,9 +146,11 @@ fun IrAnnotationContainer.getAnnotation(annotation: FqName): IrConstructorCall { ?: ((this as IrFunction).parent as IrClass).annotations.first { it.symbol.descriptor.containingDeclaration.fqNameSafe == annotation } } +const val defaultIntrinsicLocation = "org.jetbrains.kotlin.backend.common.interpreter.intrinsic.InterpreterIntrinsicsKt" fun IrAnnotationContainer.getEvaluateIntrinsicValue(): String? { if (!this.hasAnnotation(evaluateIntrinsicAnnotation)) return null - return (this.getAnnotation(evaluateIntrinsicAnnotation).getValueArgument(0) as IrConst<*>).value.toString() + val value = (this.getAnnotation(evaluateIntrinsicAnnotation).getValueArgument(0) as IrConst<*>).value.toString() + return if (value.isEmpty()) defaultIntrinsicLocation else value } fun getPrimitiveClass(fqName: String, asObject: Boolean = false): Class<*>? { diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/intrinsic/InterpreterIntrinsics.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/intrinsic/InterpreterIntrinsics.kt new file mode 100644 index 00000000000..e075de4f351 --- /dev/null +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/intrinsic/InterpreterIntrinsics.kt @@ -0,0 +1,12 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +@file:JvmName("InterpreterIntrinsicsKt") + +package org.jetbrains.kotlin.backend.common.interpreter.intrinsic + +public fun emptyArray(): Array = kotlin.emptyArray() + +public fun arrayOf(vararg elements: Any?): Array = elements as Array \ No newline at end of file diff --git a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/State.kt b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/State.kt index 18933c825e5..e0b40568904 100644 --- a/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/State.kt +++ b/compiler/ir/backend.common/src/org/jetbrains/kotlin/backend/common/interpreter/stack/State.kt @@ -16,7 +16,6 @@ import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl -import org.jetbrains.kotlin.ir.expressions.IrConst import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.defaultType @@ -166,11 +165,10 @@ class Wrapper(val value: Any, override var irClass: IrClass) : Complex(irClass, } fun getStaticMethod(irFunction: IrFunction): MethodHandle { - val annotation = irFunction.getAnnotation(evaluateIntrinsicAnnotation) - val jvmFileName = Class.forName((annotation.getValueArgument(0) as IrConst<*>).value.toString()) + val jvmClassName = Class.forName(irFunction.getEvaluateIntrinsicValue()!!) val methodType = irFunction.getMethodType() - return MethodHandles.lookup().findStatic(jvmFileName, irFunction.name.asString(), methodType) + return MethodHandles.lookup().findStatic(jvmClassName, irFunction.name.asString(), methodType) } private fun IrFunction.getMethodType(): MethodType {