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) {
|
||||
IrSyntheticBodyKind.ENUM_VALUES -> {
|
||||
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))
|
||||
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
|
||||
}
|
||||
}
|
||||
IrSyntheticBodyKind.ENUM_VALUES -> handleIntrinsicMethods(irFunction, data)
|
||||
IrSyntheticBodyKind.ENUM_VALUEOF -> handleIntrinsicMethods(irFunction, data)
|
||||
null -> irFunction.body?.interpret(data) ?: throw AssertionError("Ir function must be with body")
|
||||
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))
|
||||
data.pushReturnValue(result.toState(result.getType(irFunction.returnType)))
|
||||
|
||||
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 {
|
||||
if (irFunction.body == null) {
|
||||
val receiver = data.getVariableState(irFunction.symbol.getReceiver()!!) as Complex
|
||||
@@ -259,6 +279,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
|
||||
val overriddenOwner = overridden.owner as IrFunctionImpl
|
||||
return when {
|
||||
// TODO figure something better
|
||||
superQualifier.irClassFqName() == "kotlin.Enum" && owner.name.asString() == "hashCode" -> calculateOverridden(overriddenOwner, newStates)
|
||||
overriddenOwner.body != null -> overriddenOwner.interpret(newStates)
|
||||
superQualifier.superType == null -> calculateBuiltIns(overriddenOwner, newStates)
|
||||
@@ -461,7 +482,7 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
||||
}
|
||||
|
||||
val originalVarToInline = ParallelVisitorForInlineFun()
|
||||
.apply { this.visitElement(inlineFun.body!!.statements.first(), block.statements.last()) }
|
||||
.apply { this.visitElement(inlineFun.body!!.statements.first(), block.removeBlocks()!!) }
|
||||
.originalVarToInline
|
||||
|
||||
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 }
|
||||
}
|
||||
|
||||
const val defaultIntrinsicLocation = "org.jetbrains.kotlin.backend.common.interpreter.intrinsic.InterpreterIntrinsicsKt"
|
||||
fun IrAnnotationContainer.getEvaluateIntrinsicValue(): String? {
|
||||
if (!this.hasAnnotation(evaluateIntrinsicAnnotation)) return null
|
||||
val value = (this.getAnnotation(evaluateIntrinsicAnnotation).getValueArgument(0) as IrConst<*>).value.toString()
|
||||
return if (value.isEmpty()) defaultIntrinsicLocation else value
|
||||
return (this.getAnnotation(evaluateIntrinsicAnnotation).getValueArgument(0) as IrConst<*>).value.toString()
|
||||
}
|
||||
|
||||
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 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
|
||||
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
|
||||
// - use getter for private fields such as detailMessage in java.lang.Throwable
|
||||
val intrinsicName = property?.getEvaluateIntrinsicValue() ?: irFunction.getEvaluateIntrinsicValue()
|
||||
if (intrinsicName?.isEmpty() == true) return null
|
||||
val methodName = intrinsicName ?: (property ?: irFunction).name.toString()
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fun getStaticMethod(irFunction: IrFunction): MethodHandle {
|
||||
val jvmClassName = Class.forName(irFunction.getEvaluateIntrinsicValue()!!)
|
||||
fun getStaticMethod(irFunction: IrFunction): MethodHandle? {
|
||||
val intrinsicName = irFunction.getEvaluateIntrinsicValue()
|
||||
if (intrinsicName?.isEmpty() == true) return null
|
||||
val jvmClassName = Class.forName(intrinsicName!!)
|
||||
|
||||
val methodType = irFunction.getMethodType()
|
||||
return MethodHandles.lookup().findStatic(jvmClassName, irFunction.name.asString(), methodType)
|
||||
|
||||
Reference in New Issue
Block a user