Support interpretation for inner class
This commit is contained in:
+15
-7
@@ -281,6 +281,10 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
val isLocal = (dispatchReceiver as? Complex)?.getOriginal()?.irClass?.isLocal ?: irFunction.isLocal
|
val isLocal = (dispatchReceiver as? Complex)?.getOriginal()?.irClass?.isLocal ?: irFunction.isLocal
|
||||||
if (isLocal) valueArguments.addAll(dispatchReceiver.extractNonLocalDeclarations())
|
if (isLocal) valueArguments.addAll(dispatchReceiver.extractNonLocalDeclarations())
|
||||||
|
|
||||||
|
if (functionReceiver is Complex && irFunction.parentClassOrNull?.isInner == true) {
|
||||||
|
generateSequence(functionReceiver.outerClass) { (it.state as? Complex)?.outerClass }.forEach { valueArguments.add(it) }
|
||||||
|
}
|
||||||
|
|
||||||
return stack.newFrame(asSubFrame = irFunction.isInline || irFunction.isLocal, initPool = valueArguments) {
|
return stack.newFrame(asSubFrame = irFunction.isInline || irFunction.isLocal, initPool = valueArguments) {
|
||||||
// inline only methods are not presented in lookup table, so must be interpreted instead of execution
|
// inline only methods are not presented in lookup table, so must be interpreted instead of execution
|
||||||
val isInlineOnly = irFunction.hasAnnotation(FqName("kotlin.internal.InlineOnly"))
|
val isInlineOnly = irFunction.hasAnnotation(FqName("kotlin.internal.InlineOnly"))
|
||||||
@@ -321,20 +325,24 @@ class IrInterpreter(irModule: IrModuleFragment) {
|
|||||||
|
|
||||||
interpretValueParameters(constructorCall, owner, valueArguments).check { return it }
|
interpretValueParameters(constructorCall, owner, valueArguments).check { return it }
|
||||||
|
|
||||||
val parent = owner.parent as IrClass
|
val irClass = owner.parent as IrClass
|
||||||
val typeArguments = getTypeArguments(parent, constructorCall) { stack.getVariableState(it) } + stack.getAllTypeArguments()
|
val typeArguments = getTypeArguments(irClass, constructorCall) { stack.getVariableState(it) } + stack.getAllTypeArguments()
|
||||||
if (parent.hasAnnotation(evaluateIntrinsicAnnotation)) {
|
if (irClass.hasAnnotation(evaluateIntrinsicAnnotation)) {
|
||||||
return stack.newFrame(initPool = valueArguments) { Wrapper.getConstructorMethod(owner).invokeMethod(owner) }
|
return stack.newFrame(initPool = valueArguments) { Wrapper.getConstructorMethod(owner).invokeMethod(owner) }
|
||||||
.apply { (stack.peekReturnValue() as? Wrapper)?.typeArguments?.addAll(typeArguments) } // can be exception
|
.apply { (stack.peekReturnValue() as? Wrapper)?.typeArguments?.addAll(typeArguments) } // 'as?' because can be exception
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parent.defaultType.isArray() || parent.defaultType.isPrimitiveArray()) {
|
if (irClass.defaultType.isArray() || irClass.defaultType.isPrimitiveArray()) {
|
||||||
// array constructor doesn't have body so must be treated separately
|
// array constructor doesn't have body so must be treated separately
|
||||||
return stack.newFrame(initPool = valueArguments) { handleIntrinsicMethods(owner) }
|
return stack.newFrame(initPool = valueArguments) { handleIntrinsicMethods(owner) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val state = Common(parent).apply { this.typeArguments.addAll(typeArguments) }
|
val state = Common(irClass).apply { this.typeArguments.addAll(typeArguments) }
|
||||||
if (parent.isLocal) state.fields.addAll(stack.getAll()) // TODO save only necessary declarations
|
if (irClass.isLocal) state.fields.addAll(stack.getAll()) // TODO save only necessary declarations
|
||||||
|
if (irClass.isInner) {
|
||||||
|
constructorCall.dispatchReceiver!!.interpret().check { return it }
|
||||||
|
state.outerClass = Variable(constructorCall.symbol.owner.dispatchReceiverParameter!!.descriptor, stack.popReturnValue())
|
||||||
|
}
|
||||||
valueArguments.add(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body
|
valueArguments.add(Variable(constructorCall.getThisAsReceiver(), state)) //used to set up fields in body
|
||||||
return stack.newFrame(initPool = valueArguments + state.typeArguments) {
|
return stack.newFrame(initPool = valueArguments + state.typeArguments) {
|
||||||
val statements = constructorCall.getBody()!!.statements
|
val statements = constructorCall.getBody()!!.statements
|
||||||
|
|||||||
+4
-9
@@ -5,22 +5,19 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.common.interpreter.state
|
package org.jetbrains.kotlin.backend.common.interpreter.state
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.getLastOverridden
|
|
||||||
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
|
import org.jetbrains.kotlin.backend.common.interpreter.stack.Variable
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||||
import org.jetbrains.kotlin.ir.util.isFakeOverride
|
|
||||||
import org.jetbrains.kotlin.ir.util.isInterface
|
import org.jetbrains.kotlin.ir.util.isInterface
|
||||||
|
|
||||||
class Common private constructor(
|
class Common private constructor(
|
||||||
override val irClass: IrClass, override val fields: MutableList<Variable>, override val typeArguments: MutableList<Variable>,
|
override val irClass: IrClass, override val fields: MutableList<Variable>
|
||||||
superClass: Complex?, subClass: Complex?
|
) : Complex(irClass, fields) {
|
||||||
) : Complex(irClass, fields, superClass, subClass) {
|
|
||||||
|
|
||||||
constructor(irClass: IrClass) : this(irClass, mutableListOf(), mutableListOf(), null, null)
|
constructor(irClass: IrClass) : this(irClass, mutableListOf())
|
||||||
|
|
||||||
fun setSuperClassRecursive() {
|
fun setSuperClassRecursive() {
|
||||||
var thisClass: Common? = this
|
var thisClass: Common? = this
|
||||||
@@ -51,9 +48,7 @@ class Common private constructor(
|
|||||||
.let { getOverridden(it as IrSimpleFunction, this) }
|
.let { getOverridden(it as IrSimpleFunction, this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun copy(): State {
|
override fun copy() = Common(irClass, fields).copyFrom(this)
|
||||||
return Common(irClass, fields, typeArguments, superClass, subClass ?: this)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "Common(obj='${irClass.fqNameForIrSerialization}', super=$superClass, values=$fields)"
|
return "Common(obj='${irClass.fqNameForIrSerialization}', super=$superClass, values=$fields)"
|
||||||
|
|||||||
+13
-4
@@ -18,10 +18,11 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
|
|||||||
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
import org.jetbrains.kotlin.ir.util.fqNameForIrSerialization
|
||||||
import org.jetbrains.kotlin.ir.util.isInterface
|
import org.jetbrains.kotlin.ir.util.isInterface
|
||||||
|
|
||||||
abstract class Complex(
|
abstract class Complex(override val irClass: IrClass, override val fields: MutableList<Variable>) : State {
|
||||||
override val irClass: IrClass, override val fields: MutableList<Variable>, var superClass: Complex?, var subClass: Complex?
|
var superClass: Complex? = null
|
||||||
) : State {
|
var subClass: Complex? = null
|
||||||
abstract val typeArguments: MutableList<Variable>
|
val typeArguments: MutableList<Variable> = mutableListOf()
|
||||||
|
var outerClass: Variable? = null
|
||||||
|
|
||||||
fun setSuperClassInstance(superClass: Complex) {
|
fun setSuperClassInstance(superClass: Complex) {
|
||||||
if (this.irClass == superClass.irClass) {
|
if (this.irClass == superClass.irClass) {
|
||||||
@@ -52,6 +53,14 @@ abstract class Complex(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected fun copyFrom(other: Complex): State {
|
||||||
|
this.superClass = other.superClass
|
||||||
|
this.subClass = other.subClass ?: other
|
||||||
|
this.typeArguments.addAll(other.typeArguments)
|
||||||
|
this.outerClass = other.outerClass
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
private fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
|
private fun getIrFunction(descriptor: FunctionDescriptor): IrFunction? {
|
||||||
val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
|
val propertyGetters = irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
|
||||||
val functions = irClass.declarations.filterIsInstance<IrFunction>()
|
val functions = irClass.declarations.filterIsInstance<IrFunction>()
|
||||||
|
|||||||
+3
-6
@@ -16,9 +16,8 @@ import org.jetbrains.kotlin.ir.util.nameForIrSerialization
|
|||||||
import kotlin.math.min
|
import kotlin.math.min
|
||||||
|
|
||||||
class ExceptionState private constructor(
|
class ExceptionState private constructor(
|
||||||
override val irClass: IrClass, override val fields: MutableList<Variable>, stackTrace: List<String>, subClass: Complex? = null
|
override val irClass: IrClass, override val fields: MutableList<Variable>, stackTrace: List<String>
|
||||||
) : Complex(irClass, fields, null, subClass) {
|
) : Complex(irClass, fields) {
|
||||||
override val typeArguments: MutableList<Variable> = mutableListOf()
|
|
||||||
|
|
||||||
private lateinit var exceptionFqName: String
|
private lateinit var exceptionFqName: String
|
||||||
private val exceptionHierarchy = mutableListOf<String>()
|
private val exceptionHierarchy = mutableListOf<String>()
|
||||||
@@ -106,9 +105,7 @@ class ExceptionState private constructor(
|
|||||||
|
|
||||||
fun getThisAsCauseForException() = ExceptionData(this)
|
fun getThisAsCauseForException() = ExceptionData(this)
|
||||||
|
|
||||||
override fun copy(): State {
|
override fun copy() = ExceptionState(irClass, fields, stackTrace).copyFrom(this)
|
||||||
return ExceptionState(irClass, fields, stackTrace, subClass ?: this)
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private fun IrClass.getPropertyByName(name: String): IrProperty {
|
private fun IrClass.getPropertyByName(name: String): IrProperty {
|
||||||
|
|||||||
+2
-8
@@ -34,15 +34,11 @@ import java.lang.invoke.MethodHandle
|
|||||||
import java.lang.invoke.MethodHandles
|
import java.lang.invoke.MethodHandles
|
||||||
import java.lang.invoke.MethodType
|
import java.lang.invoke.MethodType
|
||||||
|
|
||||||
class Wrapper private constructor(
|
class Wrapper(val value: Any, override val irClass: IrClass) : Complex(irClass, mutableListOf()) {
|
||||||
val value: Any, override val irClass: IrClass, subClass: Complex?, override val typeArguments: MutableList<Variable>
|
|
||||||
) : Complex(irClass, mutableListOf(), null, subClass) {
|
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
constructor(value: Any, irClass: IrClass) : this(value, irClass, null, mutableListOf())
|
|
||||||
|
|
||||||
fun getMethod(irFunction: IrFunction): MethodHandle? {
|
fun getMethod(irFunction: IrFunction): MethodHandle? {
|
||||||
if (irFunction.getEvaluateIntrinsicValue()?.isEmpty() == true) return null // this method will handle IntrinsicEvaluator
|
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
|
// if function is actually a getter, then use "get${property.name.capitalize()}" as method name
|
||||||
@@ -198,9 +194,7 @@ class Wrapper private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun copy(): State {
|
override fun copy() = Wrapper(value, irClass).copyFrom(this)
|
||||||
return Wrapper(value, irClass, subClass ?: this, typeArguments)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return "Wrapper(obj='$typeFqName', value=$value)"
|
return "Wrapper(obj='$typeFqName', value=$value)"
|
||||||
|
|||||||
Reference in New Issue
Block a user