From 6f4f7dd090738a4e2c7292267276c826cf848869 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Mon, 22 Jun 2020 03:23:12 +0300 Subject: [PATCH] Remove coroutines from ir interpreter --- compiler/ir/ir.interpreter/build.gradle.kts | 1 - .../kotlin/ir/interpreter/IrInterpreter.kt | 103 +++++++++--------- .../jetbrains/kotlin/ir/interpreter/Label.kt | 2 +- .../intrinsics/IntrinsicEvaluator.kt | 2 +- .../intrinsics/IntrinsicImplementations.kt | 41 ++----- .../kotlin/ir/interpreter/stack/Stack.kt | 6 +- 6 files changed, 64 insertions(+), 91 deletions(-) diff --git a/compiler/ir/ir.interpreter/build.gradle.kts b/compiler/ir/ir.interpreter/build.gradle.kts index 13a919c9c95..ee70e31cb64 100644 --- a/compiler/ir/ir.interpreter/build.gradle.kts +++ b/compiler/ir/ir.interpreter/build.gradle.kts @@ -5,7 +5,6 @@ plugins { dependencies { compile(project(":compiler:ir.tree")) - compileOnly(commonDep("org.jetbrains.kotlinx", "kotlinx-coroutines-core")) { isTransitive = false } } sourceSets { diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt index e2ad954debd..e3d479d12c1 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/IrInterpreter.kt @@ -5,9 +5,6 @@ package org.jetbrains.kotlin.ir.interpreter -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.withContext -import kotlinx.coroutines.yield import org.jetbrains.kotlin.ir.interpreter.builtins.* import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterException import org.jetbrains.kotlin.ir.interpreter.exceptions.InterpreterMethodNotFoundException @@ -31,8 +28,8 @@ import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import java.lang.invoke.MethodHandle +import kotlin.concurrent.thread -private const val MAX_STACK_SIZE = 10_000 private const val MAX_COMMANDS = 500_000 class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map = emptyMap()) { @@ -72,9 +69,10 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map stack.popReturnValue().toIrExpression(expression) ReturnLabel.EXCEPTION -> { val message = (stack.popReturnValue() as ExceptionState).getFullDescription() @@ -82,14 +80,15 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map TODO("$returnLabel not supported as result of interpretation") } + } catch (e: InterpreterException) { + // TODO don't handle, throw to lowering + IrErrorExpressionImpl(expression.startOffset, expression.endOffset, expression.type, "\n" + e.message) } - } catch (e: InterpreterException) { - // TODO don't handle, throw to lowering - IrErrorExpressionImpl(expression.startOffset, expression.endOffset, expression.type, "\n" + e.message) - } + }.join() + return result } - private suspend fun IrElement.interpret(): ExecutionResult { + private fun IrElement.interpret(): ExecutionResult { try { incrementAndCheckCommands() val executionResult = when (this) { @@ -145,18 +144,14 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map irFunction.name.asString() else -> property.owner.name.asString() @@ -227,7 +222,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map ): ExecutionResult { // if irFunction is lambda and it has receiver, then first descriptor must be taken from extension receiver @@ -275,7 +270,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map() // dispatch receiver processing val rawDispatchReceiver = expression.dispatchReceiver @@ -322,7 +317,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map() @@ -403,15 +398,15 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map): ExecutionResult { + private fun interpretConst(expression: IrConst<*>): ExecutionResult { fun getSignedType(unsignedType: IrType): IrType { return when { unsignedType.isUByte() -> irBuiltIns.byteType @@ -445,7 +440,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map): ExecutionResult { + private fun interpretStatements(statements: List): ExecutionResult { var executionResult: ExecutionResult = Next for (statement in statements) { when (statement) { @@ -457,20 +452,20 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map() @@ -624,7 +619,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map return executionResult } return@flatMap when (val result = stack.popReturnValue()) { @@ -701,11 +696,11 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map return val exception = stack.peekReturnValue() as ExceptionState @@ -722,14 +717,14 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map stack.pushReturnValue(ExceptionState(exception, stack.getStackTrace())) @@ -740,7 +735,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map return executionResult } @@ -752,7 +747,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map -> state.value.toString() is Wrapper -> state.value.toString() @@ -781,7 +776,7 @@ class IrInterpreter(irModule: IrModuleFragment, private val bodyMap: Map interpretStatements(expression.statements) null -> interpretStatements(expression.statements) // is null for body of do while loop diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Label.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Label.kt index 97ca4dace29..51e4d56b373 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Label.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/Label.kt @@ -27,7 +27,7 @@ enum class ReturnLabel { } open class ExecutionResult(val returnLabel: ReturnLabel, private val owner: IrElement? = null) { - suspend fun getNextLabel(irElement: IrElement, interpret: suspend IrElement.() -> ExecutionResult): ExecutionResult { + fun getNextLabel(irElement: IrElement, interpret: IrElement.() -> ExecutionResult): ExecutionResult { return when (returnLabel) { ReturnLabel.RETURN -> when (irElement) { is IrCall, is IrReturnableBlock, is IrFunctionImpl, is IrLazyFunction -> if (owner == irElement) Next else this 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 a2be5ab4da2..7254b8c718e 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 @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.IrFunction internal class IntrinsicEvaluator { - suspend fun evaluate(irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult): ExecutionResult { + fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult { return when { EmptyArray.equalTo(irFunction) -> EmptyArray.evaluate(irFunction, stack, interpret) ArrayOf.equalTo(irFunction) -> ArrayOf.evaluate(irFunction, stack, interpret) 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 7325fcd2e23..ff37fac91da 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 @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.ir.interpreter.intrinsics -import kotlinx.coroutines.runBlocking import org.jetbrains.kotlin.ir.interpreter.* import org.jetbrains.kotlin.ir.interpreter.stack.Stack import org.jetbrains.kotlin.ir.interpreter.stack.Variable @@ -19,7 +18,7 @@ import org.jetbrains.kotlin.ir.util.* internal sealed class IntrinsicBase { abstract fun equalTo(irFunction: IrFunction): Boolean - abstract suspend fun evaluate(irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult): ExecutionResult + abstract fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult } internal object EmptyArray : IntrinsicBase() { @@ -28,9 +27,7 @@ internal object EmptyArray : IntrinsicBase() { return fqName in setOf("kotlin.emptyArray", "kotlin.ArrayIntrinsicsKt.emptyArray") } - override suspend fun evaluate( - irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult - ): ExecutionResult { + override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult { val typeArguments = irFunction.typeParameters.map { stack.getVariable(it.symbol) } stack.pushReturnValue(emptyArray().toState(irFunction.returnType).apply { addTypeArguments(typeArguments) }) return Next @@ -43,9 +40,7 @@ internal object ArrayOf : IntrinsicBase() { return fqName == "kotlin.arrayOf" } - override suspend fun evaluate( - irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult - ): ExecutionResult { + override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult { val array = irFunction.getArgsForMethodInvocation(stack.getAll()).toTypedArray() val typeArguments = irFunction.typeParameters.map { stack.getVariable(it.symbol) } stack.pushReturnValue(array.toState(irFunction.returnType).apply { addTypeArguments(typeArguments) }) @@ -59,9 +54,7 @@ internal object ArrayOfNulls : IntrinsicBase() { return fqName == "kotlin.arrayOfNulls" } - override suspend fun evaluate( - irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult - ): ExecutionResult { + override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult { val size = stack.getVariable(irFunction.valueParameters.first().symbol).state.asInt() val array = arrayOfNulls(size) val typeArguments = irFunction.typeParameters.map { stack.getVariable(it.symbol) } @@ -76,9 +69,7 @@ internal object EnumValues : IntrinsicBase() { return (fqName == "kotlin.enumValues" || fqName.endsWith(".values")) && irFunction.valueParameters.isEmpty() } - override suspend fun evaluate( - irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult - ): ExecutionResult { + override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult { val enumClass = when (irFunction.fqNameWhenAvailable.toString()) { "kotlin.enumValues" -> stack.getVariable(irFunction.typeParameters.first().symbol).state.irClass else -> irFunction.parent as IrClass @@ -97,9 +88,7 @@ internal object EnumValueOf : IntrinsicBase() { return (fqName == "kotlin.enumValueOf" || fqName.endsWith(".valueOf")) && irFunction.valueParameters.size == 1 } - override suspend fun evaluate( - irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult - ): ExecutionResult { + override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult { val enumClass = when (irFunction.fqNameWhenAvailable.toString()) { "kotlin.enumValueOf" -> stack.getVariable(irFunction.typeParameters.first().symbol).state.irClass else -> irFunction.parent as IrClass @@ -119,9 +108,7 @@ internal object RegexReplace : IntrinsicBase() { return fqName == "kotlin.text.Regex.replace" && irFunction.valueParameters.size == 2 } - override suspend fun evaluate( - irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult - ): ExecutionResult { + override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult { val states = stack.getAll().map { it.state } val regex = states.filterIsInstance().single().value as Regex val input = states.filterIsInstance>().single().asString() @@ -129,7 +116,7 @@ internal object RegexReplace : IntrinsicBase() { val matchResultParameter = transform.valueParameters.single() val result = regex.replace(input) { val itAsState = Variable(matchResultParameter.symbol, Wrapper(it, matchResultParameter.type.classOrNull!!.owner)) - runBlocking { stack.newFrame(initPool = listOf(itAsState)) { transform.interpret() } }//.check { return it } + stack.newFrame(initPool = listOf(itAsState)) { transform.interpret() }//.check { return it } stack.popReturnValue().asString() } stack.pushReturnValue(result.toState(irFunction.returnType)) @@ -143,9 +130,7 @@ internal object EnumHashCode : IntrinsicBase() { return fqName == "kotlin.Enum.hashCode" } - override suspend fun evaluate( - irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult - ): ExecutionResult { + override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult { val hashCode = stack.getAll().single().state.hashCode() stack.pushReturnValue(hashCode.toState(irFunction.returnType)) return Next @@ -158,9 +143,7 @@ internal object JsPrimitives : IntrinsicBase() { return fqName == "kotlin.Long." || fqName == "kotlin.Char." } - override suspend fun evaluate( - irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult - ): ExecutionResult { + override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult { when (irFunction.fqNameWhenAvailable.toString()) { "kotlin.Long." -> { val low = stack.getVariable(irFunction.valueParameters[0].symbol).state.asInt() @@ -182,9 +165,7 @@ internal object ArrayConstructor : IntrinsicBase() { return fqName.matches("kotlin\\.(Byte|Char|Short|Int|Long|Float|Double|Boolean|)Array\\.".toRegex()) } - override suspend fun evaluate( - irFunction: IrFunction, stack: Stack, interpret: suspend IrElement.() -> ExecutionResult - ): ExecutionResult { + override fun evaluate(irFunction: IrFunction, stack: Stack, interpret: IrElement.() -> ExecutionResult): ExecutionResult { val sizeDescriptor = irFunction.valueParameters[0].symbol val size = stack.getVariable(sizeDescriptor).state.asInt() val arrayValue = MutableList(size) { 0 } diff --git a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Stack.kt b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Stack.kt index 1a5e66332d9..9ec877c690e 100644 --- a/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Stack.kt +++ b/compiler/ir/ir.interpreter/src/org/jetbrains/kotlin/ir/interpreter/stack/Stack.kt @@ -19,9 +19,7 @@ import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult internal interface Stack { - suspend fun newFrame( - asSubFrame: Boolean = false, initPool: List = listOf(), block: suspend () -> ExecutionResult - ): ExecutionResult + fun newFrame(asSubFrame: Boolean = false, initPool: List = listOf(), block: () -> ExecutionResult): ExecutionResult fun setCurrentFrameName(irFunction: IrFunction) fun getStackTrace(): List @@ -43,7 +41,7 @@ internal class StackImpl : Stack { private val frameList = mutableListOf(FrameContainer()) // first frame is default, it is easier to work when last() is not null private fun getCurrentFrame() = frameList.last() - override suspend fun newFrame(asSubFrame: Boolean, initPool: List, block: suspend () -> ExecutionResult): ExecutionResult { + override fun newFrame(asSubFrame: Boolean, initPool: List, block: () -> ExecutionResult): ExecutionResult { val typeArgumentsPool = initPool.filter { it.symbol is IrTypeParameterSymbol } val valueArguments = initPool.filter { it.symbol !is IrTypeParameterSymbol } val newFrame = InterpreterFrame(valueArguments.toMutableList(), typeArgumentsPool)