[JVM] Simplify StoreLoadInterpreter and StoreLoadFrame
This commit is contained in:
+6
-41
@@ -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] -> {
|
||||
|
||||
+17
-32
@@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user