[JVM] Simplify StoreLoadInterpreter and StoreLoadFrame

This commit is contained in:
Ivan Kylchik
2023-09-05 16:29:54 +02:00
committed by Space Team
parent 0e9d884b0b
commit f9868f757b
2 changed files with 23 additions and 73 deletions
@@ -36,7 +36,6 @@ package org.jetbrains.kotlin.codegen.optimization.temporaryVals
import org.jetbrains.kotlin.codegen.optimization.common.FastAnalyzer
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Opcodes.API_VERSION
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
@@ -44,59 +43,25 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Value
interface StoreLoadValue : Value
abstract class StoreLoadInterpreter<V : StoreLoadValue> : Interpreter<V>(API_VERSION) {
abstract fun uninitialized(): V
abstract fun valueParameter(type: Type): V
abstract fun store(insn: VarInsnNode): V
abstract fun load(insn: VarInsnNode, value: V)
abstract fun iinc(insn: IincInsnNode, value: V): V
}
abstract class StoreLoadInterpreter<V : StoreLoadValue> : Interpreter<V>(API_VERSION)
@Suppress("UNCHECKED_CAST")
class StoreLoadFrame<V : StoreLoadValue>(val maxLocals: Int) : Frame<V>(maxLocals, 0) {
private val locals = arrayOfNulls<StoreLoadValue>(maxLocals)
operator fun get(index: Int): V =
locals[index] as V
operator fun set(index: Int, newValue: V) {
locals[index] = newValue
}
fun init(other: StoreLoadFrame<V>): StoreLoadFrame<V> {
System.arraycopy(other.locals, 0, this.locals, 0, locals.size)
return this
}
fun execute(insn: AbstractInsnNode, interpreter: StoreLoadInterpreter<V>) {
override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<V>) {
when (insn.opcode) {
in Opcodes.ISTORE..Opcodes.ASTORE -> {
val varInsn = insn as VarInsnNode
locals[varInsn.`var`] = interpreter.store(varInsn)
setLocal(varInsn.`var`, interpreter.copyOperation(varInsn, null))
}
in Opcodes.ILOAD..Opcodes.ALOAD -> {
val varInsn = insn as VarInsnNode
interpreter.load(varInsn, this[varInsn.`var`])
interpreter.copyOperation(varInsn, this.getLocal(varInsn.`var`))
}
Opcodes.IINC -> {
val iincInsn = insn as IincInsnNode
interpreter.iinc(iincInsn, this[iincInsn.`var`])
interpreter.unaryOperation(iincInsn, this.getLocal(iincInsn.`var`))
}
}
}
fun merge(other: StoreLoadFrame<V>, interpreter: StoreLoadInterpreter<V>): Boolean {
var changes = false
for (i in locals.indices) {
val oldValue = this[i]
val newValue = interpreter.merge(oldValue, other[i])
if (newValue != oldValue) {
changes = true
this[i] = newValue
}
}
return changes
}
}
class FastStoreLoadAnalyzer<V : StoreLoadValue>(
@@ -192,7 +157,7 @@ class FastStoreLoadAnalyzer<V : StoreLoadValue>(
val oldFrame = getFrame(dest)
val changes = when {
oldFrame == null -> {
setFrame(dest, newFrame(frame.maxLocals, 0).init(frame))
setFrame(dest, newFrame(frame.maxLocals, 0).apply { init(frame) })
true
}
!isMergeNode[dest] -> {
@@ -12,7 +12,6 @@ import org.jetbrains.kotlin.utils.SmartSet
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.IincInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
@@ -161,31 +160,28 @@ class TemporaryValsAnalyzer {
private val storeInsnToStoreData: Map<AbstractInsnNode, StoreData>
) : StoreLoadInterpreter<StoredValue>() {
override fun uninitialized(): StoredValue = StoredValue.Unknown
override fun newEmptyValue(local: Int): StoredValue = StoredValue.Unknown
override fun newValue(type: Type?): StoredValue = StoredValue.Unknown
override fun valueParameter(type: Type): StoredValue = StoredValue.Unknown
override fun store(insn: VarInsnNode): StoredValue {
val temporaryValData = storeInsnToStoreData[insn]
if (temporaryValData != null) {
return temporaryValData.value
}
return StoredValue.Unknown
}
override fun load(insn: VarInsnNode, value: StoredValue) {
if (value is StoredValue.DirtyStore) {
override fun copyOperation(insn: AbstractInsnNode, value: StoredValue?): StoredValue {
if (value == null) {
val temporaryValData = storeInsnToStoreData[insn]
if (temporaryValData != null) {
return temporaryValData.value
}
} else if (value is StoredValue.DirtyStore) {
// If we load a dirty value, invalidate all related temporary vals.
value.temporaryVals.forEach { it.isDirty = true }
} else if (value is StoredValue.Store) {
// Keep track of a load instruction
value.temporaryVal.loads.add(insn)
}
return StoredValue.Unknown
}
override fun iinc(insn: IincInsnNode, value: StoredValue): StoredValue {
override fun unaryOperation(insn: AbstractInsnNode, value: StoredValue): StoredValue {
if (insn.opcode != Opcodes.IINC) return value
when (value) {
is StoredValue.Store ->
value.temporaryVal.isDirty = true
@@ -222,37 +218,26 @@ class TemporaryValsAnalyzer {
else -> emptySet()
}
override fun copyOperation(insn: AbstractInsnNode?, value: StoredValue?): StoredValue {
TODO("Not yet implemented")
}
override fun newOperation(insn: AbstractInsnNode?): StoredValue {
TODO("Not yet implemented")
}
override fun unaryOperation(insn: AbstractInsnNode?, value: StoredValue?): StoredValue {
TODO("Not yet implemented")
error("Should not be called")
}
override fun binaryOperation(insn: AbstractInsnNode?, value1: StoredValue?, value2: StoredValue?): StoredValue {
TODO("Not yet implemented")
error("Should not be called")
}
override fun ternaryOperation(
insn: AbstractInsnNode?,
value1: StoredValue?,
value2: StoredValue?,
value3: StoredValue?,
insn: AbstractInsnNode?, value1: StoredValue?, value2: StoredValue?, value3: StoredValue?
): StoredValue {
TODO("Not yet implemented")
error("Should not be called")
}
override fun naryOperation(insn: AbstractInsnNode?, values: MutableList<out StoredValue>?): StoredValue {
TODO("Not yet implemented")
error("Should not be called")
}
override fun returnOperation(insn: AbstractInsnNode?, value: StoredValue?, expected: StoredValue?) {
TODO("Not yet implemented")
error("Should not be called")
}
}
}