Implement cache for enum entries and objects

This commit is contained in:
Ivan Kylchik
2020-04-15 13:34:13 +03:00
parent 0b0550f562
commit a14e8e4c28
@@ -37,7 +37,10 @@ class IrInterpreter(irModule: IrModuleFragment) {
private val stack = StackImpl() private val stack = StackImpl()
private var commandCount = 0 private var commandCount = 0
private val mapOfEnums = mutableMapOf<Pair<IrClass, String>, Complex>() companion object {
private val mapOfEnums = mutableMapOf<String, Complex>()
private val mapOfObjects = mutableMapOf<String, Complex>()
}
private fun Any?.getType(defaultType: IrType): IrType { private fun Any?.getType(defaultType: IrType): IrType {
return when (this) { return when (this) {
@@ -518,31 +521,40 @@ class IrInterpreter(irModule: IrModuleFragment) {
private fun interpretGetObjectValue(expression: IrGetObjectValue): ExecutionResult { private fun interpretGetObjectValue(expression: IrGetObjectValue): ExecutionResult {
val owner = expression.symbol.owner val owner = expression.symbol.owner
if (owner.hasAnnotation(evaluateIntrinsicAnnotation)) { val objectSignature = owner.fqNameWhenAvailable.toString()
stack.pushReturnValue(Wrapper.getCompanionObject(owner)) mapOfObjects[objectSignature]?.let { return Next.apply { stack.pushReturnValue(it) } }
return Next
val objectState = when {
owner.hasAnnotation(evaluateIntrinsicAnnotation) -> Wrapper.getCompanionObject(owner)
else -> Common(owner).apply { setSuperClassRecursive() }
} }
stack.pushReturnValue(Common(owner).apply { setSuperClassRecursive() }) mapOfObjects[objectSignature] = objectState
stack.pushReturnValue(objectState)
return Next return Next
} }
private suspend fun interpretGetEnumValue(expression: IrGetEnumValue): ExecutionResult { private suspend fun interpretGetEnumValue(expression: IrGetEnumValue): ExecutionResult {
val enumEntry = expression.symbol.owner val enumEntry = expression.symbol.owner
val enumSignature = Pair(enumEntry.parentAsClass, enumEntry.name.asString()) val enumSignature = enumEntry.fqNameWhenAvailable.toString()
mapOfEnums[enumSignature]?.let { return Next.apply { stack.pushReturnValue(it) } } mapOfEnums[enumSignature]?.let { return Next.apply { stack.pushReturnValue(it) } }
val enumClass = enumEntry.symbol.owner.parentAsClass val enumClass = enumEntry.symbol.owner.parentAsClass
if (enumClass.hasAnnotation(evaluateIntrinsicAnnotation)) { val valueOfFun = enumClass.declarations.single { it.nameForIrSerialization.asString() == "valueOf" } as IrFunction
val valueOfFun = enumClass.declarations.single { it.nameForIrSerialization.asString() == "valueOf" } as IrFunction enumClass.declarations.filterIsInstance<IrEnumEntry>().forEach {
val enumName = Variable(valueOfFun.valueParameters.first().descriptor, enumEntry.name.asString().toState(irBuiltIns.stringType)) val executionResult = when {
return stack.newFrame(initPool = listOf(enumName)) { enumClass.hasAnnotation(evaluateIntrinsicAnnotation) -> {
Wrapper.getEnumEntry(enumClass)!!.invokeMethod(valueOfFun) val enumEntryName = it.name.asString().toState(irBuiltIns.stringType)
}.apply { if (this.returnLabel == ReturnLabel.NEXT) mapOfEnums[enumSignature] = stack.peekReturnValue() as Wrapper } val enumNameAsVariable = Variable(valueOfFun.valueParameters.first().descriptor, enumEntryName)
} stack.newFrame(initPool = listOf(enumNameAsVariable)) { Wrapper.getEnumEntry(enumClass)!!.invokeMethod(valueOfFun) }
// TODO extract common code }
return interpretEnumEntry(enumEntry).apply { else -> interpretEnumEntry(it)
if (this.returnLabel == ReturnLabel.NEXT) mapOfEnums[enumSignature] = stack.peekReturnValue() as Common }
executionResult.check { result -> return result }
mapOfEnums[it.fqNameWhenAvailable.toString()] = stack.popReturnValue() as Complex
} }
stack.pushReturnValue(mapOfEnums[enumSignature]!!)
return Next
} }
private suspend fun interpretEnumEntry(enumEntry: IrEnumEntry): ExecutionResult { private suspend fun interpretEnumEntry(enumEntry: IrEnumEntry): ExecutionResult {