Move intrinsic handling inside IrInterpreter class
This commit is contained in:
+49
-28
@@ -181,32 +181,8 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
when (val kind = (irFunction.body as? IrSyntheticBody)?.kind) {
|
when (val kind = (irFunction.body as? IrSyntheticBody)?.kind) {
|
||||||
IrSyntheticBodyKind.ENUM_VALUES -> {
|
IrSyntheticBodyKind.ENUM_VALUES -> handleIntrinsicMethods(irFunction, data)
|
||||||
val enumClass = irFunction.parentAsClass
|
IrSyntheticBodyKind.ENUM_VALUEOF -> handleIntrinsicMethods(irFunction, data)
|
||||||
val enumEntries = enumClass.declarations
|
|
||||||
.filterIsInstance<IrEnumEntry>()
|
|
||||||
.map { entry ->
|
|
||||||
entry.interpret(data).also { if (it != Code.NEXT) return it }
|
|
||||||
data.popReturnValue() as Common
|
|
||||||
}
|
|
||||||
data.pushReturnValue(enumEntries.toTypedArray().toState(irBuiltIns.arrayClass.defaultType))
|
|
||||||
Code.NEXT
|
|
||||||
}
|
|
||||||
IrSyntheticBodyKind.ENUM_VALUEOF -> {
|
|
||||||
val enumClass = irFunction.parentAsClass
|
|
||||||
val enumEntryName = (data.getAll().single().state as Primitive<*>).value.toString()
|
|
||||||
val enumEntry = enumClass.declarations
|
|
||||||
.filterIsInstance<IrEnumEntry>()
|
|
||||||
.singleOrNull { it.name.asString() == enumEntryName }
|
|
||||||
if (enumEntry == null) {
|
|
||||||
val message = "No enum constant ${enumClass.fqNameForIrSerialization}.$enumEntryName"
|
|
||||||
data.pushReturnValue(ExceptionState(IllegalArgumentException(message), illegalArgumentException, stackTrace))
|
|
||||||
Code.EXCEPTION
|
|
||||||
} else {
|
|
||||||
enumEntry.interpret(data).also { if (it != Code.NEXT) return it }
|
|
||||||
Code.NEXT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
null -> irFunction.body?.interpret(data) ?: throw AssertionError("Ir function must be with body")
|
null -> irFunction.body?.interpret(data) ?: throw AssertionError("Ir function must be with body")
|
||||||
else -> throw AssertionError("Unsupported IrSyntheticBodyKind $kind")
|
else -> throw AssertionError("Unsupported IrSyntheticBodyKind $kind")
|
||||||
}
|
}
|
||||||
@@ -215,13 +191,57 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun MethodHandle.invokeMethod(irFunction: IrFunction, data: Frame): Code {
|
private suspend fun MethodHandle?.invokeMethod(irFunction: IrFunction, data: Frame): Code {
|
||||||
|
this ?: return handleIntrinsicMethods(irFunction, data)
|
||||||
val result = this.invokeWithArguments(irFunction.getArgsForMethodInvocation(data))
|
val result = this.invokeWithArguments(irFunction.getArgsForMethodInvocation(data))
|
||||||
data.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
data.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
||||||
|
|
||||||
return Code.NEXT
|
return Code.NEXT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private suspend fun handleIntrinsicMethods(irFunction: IrFunction, data: Frame): Code {
|
||||||
|
when (irFunction.name.asString()) {
|
||||||
|
"emptyArray" -> {
|
||||||
|
val result = emptyArray<Any?>()
|
||||||
|
data.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
||||||
|
}
|
||||||
|
"arrayOf" -> {
|
||||||
|
val result = irFunction.getArgsForMethodInvocation(data).toTypedArray()
|
||||||
|
data.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
||||||
|
}
|
||||||
|
"arrayOfNulls" -> {
|
||||||
|
val result = arrayOfNulls<Any?>(irFunction.getArgsForMethodInvocation(data).first() as Int)
|
||||||
|
data.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
||||||
|
}
|
||||||
|
"values", "enumValues" -> {
|
||||||
|
val enumClass = irFunction.parentAsClass
|
||||||
|
val enumEntries = enumClass.declarations
|
||||||
|
.filterIsInstance<IrEnumEntry>()
|
||||||
|
.map { entry ->
|
||||||
|
entry.interpret(data).also { if (it != Code.NEXT) return it }
|
||||||
|
data.popReturnValue() as Common
|
||||||
|
}
|
||||||
|
data.pushReturnValue(enumEntries.toTypedArray().toState(irBuiltIns.arrayClass.defaultType))
|
||||||
|
}
|
||||||
|
"valueOf", "enumValueOf" -> {
|
||||||
|
val enumClass = irFunction.parentAsClass
|
||||||
|
val enumEntryName = (data.getAll().single().state as Primitive<*>).value.toString()
|
||||||
|
val enumEntry = enumClass.declarations
|
||||||
|
.filterIsInstance<IrEnumEntry>()
|
||||||
|
.singleOrNull { it.name.asString() == enumEntryName }
|
||||||
|
if (enumEntry == null) {
|
||||||
|
val message = "No enum constant ${enumClass.fqNameForIrSerialization}.$enumEntryName"
|
||||||
|
data.pushReturnValue(ExceptionState(IllegalArgumentException(message), illegalArgumentException, stackTrace))
|
||||||
|
} else {
|
||||||
|
enumEntry.interpret(data).also { if (it != Code.NEXT) return it }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> throw AssertionError("Unsupported intrinsic ${irFunction.name}")
|
||||||
|
}
|
||||||
|
|
||||||
|
return Code.NEXT
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun calculateAbstract(irFunction: IrFunction, data: Frame): Code {
|
private suspend fun calculateAbstract(irFunction: IrFunction, data: Frame): Code {
|
||||||
if (irFunction.body == null) {
|
if (irFunction.body == null) {
|
||||||
val receiver = data.getVariableState(irFunction.symbol.getReceiver()!!) as Complex
|
val receiver = data.getVariableState(irFunction.symbol.getReceiver()!!) as Complex
|
||||||
@@ -259,6 +279,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
|
|
||||||
val overriddenOwner = overridden.owner as IrFunctionImpl
|
val overriddenOwner = overridden.owner as IrFunctionImpl
|
||||||
return when {
|
return when {
|
||||||
|
// TODO figure something better
|
||||||
superQualifier.irClassFqName() == "kotlin.Enum" && owner.name.asString() == "hashCode" -> calculateOverridden(overriddenOwner, newStates)
|
superQualifier.irClassFqName() == "kotlin.Enum" && owner.name.asString() == "hashCode" -> calculateOverridden(overriddenOwner, newStates)
|
||||||
overriddenOwner.body != null -> overriddenOwner.interpret(newStates)
|
overriddenOwner.body != null -> overriddenOwner.interpret(newStates)
|
||||||
superQualifier.superType == null -> calculateBuiltIns(overriddenOwner, newStates)
|
superQualifier.superType == null -> calculateBuiltIns(overriddenOwner, newStates)
|
||||||
@@ -461,7 +482,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val originalVarToInline = ParallelVisitorForInlineFun()
|
val originalVarToInline = ParallelVisitorForInlineFun()
|
||||||
.apply { this.visitElement(inlineFun.body!!.statements.first(), block.statements.last()) }
|
.apply { this.visitElement(inlineFun.body!!.statements.first(), block.removeBlocks()!!) }
|
||||||
.originalVarToInline
|
.originalVarToInline
|
||||||
|
|
||||||
val frameForWrapper = InterpreterFrame()
|
val frameForWrapper = InterpreterFrame()
|
||||||
|
|||||||
+1
-3
@@ -143,11 +143,9 @@ fun IrAnnotationContainer.getAnnotation(annotation: FqName): IrConstructorCall {
|
|||||||
?: ((this as IrFunction).parent as IrClass).annotations.first { it.symbol.descriptor.containingDeclaration.fqNameSafe == annotation }
|
?: ((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? {
|
fun IrAnnotationContainer.getEvaluateIntrinsicValue(): String? {
|
||||||
if (!this.hasAnnotation(evaluateIntrinsicAnnotation)) return null
|
if (!this.hasAnnotation(evaluateIntrinsicAnnotation)) return null
|
||||||
val value = (this.getAnnotation(evaluateIntrinsicAnnotation).getValueArgument(0) as IrConst<*>).value.toString()
|
return (this.getAnnotation(evaluateIntrinsicAnnotation).getValueArgument(0) as IrConst<*>).value.toString()
|
||||||
return if (value.isEmpty()) defaultIntrinsicLocation else value
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPrimitiveClass(fqName: String, asObject: Boolean = false): Class<*>? {
|
fun getPrimitiveClass(fqName: String, asObject: Boolean = false): Class<*>? {
|
||||||
|
|||||||
-14
@@ -1,14 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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<Any?> = kotlin.emptyArray()
|
|
||||||
|
|
||||||
public fun arrayOf(vararg elements: Any?): Array<Any?> = elements as Array<Any?>
|
|
||||||
|
|
||||||
public fun arrayOfNulls(size: Int): Array<Any?> = arrayOfNulls<Any?>(size)
|
|
||||||
+6
-3
@@ -159,7 +159,7 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
|
|||||||
private val typeFqName = irClass.fqNameForIrSerialization.toUnsafe()
|
private val typeFqName = irClass.fqNameForIrSerialization.toUnsafe()
|
||||||
private val receiverClass = irClass.defaultType.getClass(true)
|
private val receiverClass = irClass.defaultType.getClass(true)
|
||||||
|
|
||||||
fun getMethod(irFunction: IrFunction): MethodHandle {
|
fun getMethod(irFunction: IrFunction): MethodHandle? {
|
||||||
// if function is actually a getter, then use property name as method name
|
// if function is actually a getter, then use property name as method name
|
||||||
val property = (irFunction as? IrFunctionImpl)?.correspondingPropertySymbol?.owner
|
val property = (irFunction as? IrFunctionImpl)?.correspondingPropertySymbol?.owner
|
||||||
|
|
||||||
@@ -167,6 +167,7 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
|
|||||||
// for example: - method 'get' in kotlin StringBuilder is actually 'charAt' in java StringBuilder
|
// for example: - method 'get' in kotlin StringBuilder is actually 'charAt' in java StringBuilder
|
||||||
// - use getter for private fields such as detailMessage in java.lang.Throwable
|
// - use getter for private fields such as detailMessage in java.lang.Throwable
|
||||||
val intrinsicName = property?.getEvaluateIntrinsicValue() ?: irFunction.getEvaluateIntrinsicValue()
|
val intrinsicName = property?.getEvaluateIntrinsicValue() ?: irFunction.getEvaluateIntrinsicValue()
|
||||||
|
if (intrinsicName?.isEmpty() == true) return null
|
||||||
val methodName = intrinsicName ?: (property ?: irFunction).name.toString()
|
val methodName = intrinsicName ?: (property ?: irFunction).name.toString()
|
||||||
|
|
||||||
val methodType = irFunction.getMethodType()
|
val methodType = irFunction.getMethodType()
|
||||||
@@ -184,8 +185,10 @@ class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass,
|
|||||||
return MethodHandles.lookup().findConstructor(irConstructor.returnType.getClass(true), methodType)
|
return MethodHandles.lookup().findConstructor(irConstructor.returnType.getClass(true), methodType)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getStaticMethod(irFunction: IrFunction): MethodHandle {
|
fun getStaticMethod(irFunction: IrFunction): MethodHandle? {
|
||||||
val jvmClassName = Class.forName(irFunction.getEvaluateIntrinsicValue()!!)
|
val intrinsicName = irFunction.getEvaluateIntrinsicValue()
|
||||||
|
if (intrinsicName?.isEmpty() == true) return null
|
||||||
|
val jvmClassName = Class.forName(intrinsicName!!)
|
||||||
|
|
||||||
val methodType = irFunction.getMethodType()
|
val methodType = irFunction.getMethodType()
|
||||||
return MethodHandles.lookup().findStatic(jvmClassName, irFunction.name.asString(), methodType)
|
return MethodHandles.lookup().findStatic(jvmClassName, irFunction.name.asString(), methodType)
|
||||||
|
|||||||
Reference in New Issue
Block a user