[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.kotlin.codegen.optimization.common.FastAnalyzer
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes.API_VERSION
|
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.*
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
|
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
|
interface StoreLoadValue : Value
|
||||||
|
|
||||||
abstract class StoreLoadInterpreter<V : StoreLoadValue> : Interpreter<V>(API_VERSION) {
|
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
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
class StoreLoadFrame<V : StoreLoadValue>(val maxLocals: Int) : Frame<V>(maxLocals, 0) {
|
class StoreLoadFrame<V : StoreLoadValue>(val maxLocals: Int) : Frame<V>(maxLocals, 0) {
|
||||||
private val locals = arrayOfNulls<StoreLoadValue>(maxLocals)
|
override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<V>) {
|
||||||
|
|
||||||
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>) {
|
|
||||||
when (insn.opcode) {
|
when (insn.opcode) {
|
||||||
in Opcodes.ISTORE..Opcodes.ASTORE -> {
|
in Opcodes.ISTORE..Opcodes.ASTORE -> {
|
||||||
val varInsn = insn as VarInsnNode
|
val varInsn = insn as VarInsnNode
|
||||||
locals[varInsn.`var`] = interpreter.store(varInsn)
|
setLocal(varInsn.`var`, interpreter.copyOperation(varInsn, null))
|
||||||
}
|
}
|
||||||
in Opcodes.ILOAD..Opcodes.ALOAD -> {
|
in Opcodes.ILOAD..Opcodes.ALOAD -> {
|
||||||
val varInsn = insn as VarInsnNode
|
val varInsn = insn as VarInsnNode
|
||||||
interpreter.load(varInsn, this[varInsn.`var`])
|
interpreter.copyOperation(varInsn, this.getLocal(varInsn.`var`))
|
||||||
}
|
}
|
||||||
Opcodes.IINC -> {
|
Opcodes.IINC -> {
|
||||||
val iincInsn = insn as IincInsnNode
|
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>(
|
class FastStoreLoadAnalyzer<V : StoreLoadValue>(
|
||||||
@@ -192,7 +157,7 @@ class FastStoreLoadAnalyzer<V : StoreLoadValue>(
|
|||||||
val oldFrame = getFrame(dest)
|
val oldFrame = getFrame(dest)
|
||||||
val changes = when {
|
val changes = when {
|
||||||
oldFrame == null -> {
|
oldFrame == null -> {
|
||||||
setFrame(dest, newFrame(frame.maxLocals, 0).init(frame))
|
setFrame(dest, newFrame(frame.maxLocals, 0).apply { init(frame) })
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
!isMergeNode[dest] -> {
|
!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.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
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.MethodNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.VarInsnNode
|
||||||
|
|
||||||
@@ -161,31 +160,28 @@ class TemporaryValsAnalyzer {
|
|||||||
private val storeInsnToStoreData: Map<AbstractInsnNode, StoreData>
|
private val storeInsnToStoreData: Map<AbstractInsnNode, StoreData>
|
||||||
) : StoreLoadInterpreter<StoredValue>() {
|
) : 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 newValue(type: Type?): StoredValue = StoredValue.Unknown
|
||||||
|
|
||||||
override fun valueParameter(type: Type): StoredValue = StoredValue.Unknown
|
override fun copyOperation(insn: AbstractInsnNode, value: StoredValue?): StoredValue {
|
||||||
|
if (value == null) {
|
||||||
override fun store(insn: VarInsnNode): StoredValue {
|
val temporaryValData = storeInsnToStoreData[insn]
|
||||||
val temporaryValData = storeInsnToStoreData[insn]
|
if (temporaryValData != null) {
|
||||||
if (temporaryValData != null) {
|
return temporaryValData.value
|
||||||
return temporaryValData.value
|
}
|
||||||
}
|
} else if (value is StoredValue.DirtyStore) {
|
||||||
return StoredValue.Unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun load(insn: VarInsnNode, value: StoredValue) {
|
|
||||||
if (value is StoredValue.DirtyStore) {
|
|
||||||
// If we load a dirty value, invalidate all related temporary vals.
|
// If we load a dirty value, invalidate all related temporary vals.
|
||||||
value.temporaryVals.forEach { it.isDirty = true }
|
value.temporaryVals.forEach { it.isDirty = true }
|
||||||
} else if (value is StoredValue.Store) {
|
} else if (value is StoredValue.Store) {
|
||||||
// Keep track of a load instruction
|
// Keep track of a load instruction
|
||||||
value.temporaryVal.loads.add(insn)
|
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) {
|
when (value) {
|
||||||
is StoredValue.Store ->
|
is StoredValue.Store ->
|
||||||
value.temporaryVal.isDirty = true
|
value.temporaryVal.isDirty = true
|
||||||
@@ -222,37 +218,26 @@ class TemporaryValsAnalyzer {
|
|||||||
else -> emptySet()
|
else -> emptySet()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun copyOperation(insn: AbstractInsnNode?, value: StoredValue?): StoredValue {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun newOperation(insn: AbstractInsnNode?): StoredValue {
|
override fun newOperation(insn: AbstractInsnNode?): StoredValue {
|
||||||
TODO("Not yet implemented")
|
error("Should not be called")
|
||||||
}
|
|
||||||
|
|
||||||
override fun unaryOperation(insn: AbstractInsnNode?, value: StoredValue?): StoredValue {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun binaryOperation(insn: AbstractInsnNode?, value1: StoredValue?, value2: StoredValue?): StoredValue {
|
override fun binaryOperation(insn: AbstractInsnNode?, value1: StoredValue?, value2: StoredValue?): StoredValue {
|
||||||
TODO("Not yet implemented")
|
error("Should not be called")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun ternaryOperation(
|
override fun ternaryOperation(
|
||||||
insn: AbstractInsnNode?,
|
insn: AbstractInsnNode?, value1: StoredValue?, value2: StoredValue?, value3: StoredValue?
|
||||||
value1: StoredValue?,
|
|
||||||
value2: StoredValue?,
|
|
||||||
value3: StoredValue?,
|
|
||||||
): StoredValue {
|
): StoredValue {
|
||||||
TODO("Not yet implemented")
|
error("Should not be called")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun naryOperation(insn: AbstractInsnNode?, values: MutableList<out StoredValue>?): StoredValue {
|
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?) {
|
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