From f9868f757bddd18e87e53d415147a500c09274a6 Mon Sep 17 00:00:00 2001 From: Ivan Kylchik Date: Tue, 5 Sep 2023 16:29:54 +0200 Subject: [PATCH] [JVM] Simplify `StoreLoadInterpreter` and `StoreLoadFrame` --- .../temporaryVals/FastStoreLoadAnalyzer.kt | 47 +++--------------- .../temporaryVals/TemporaryVals.kt | 49 +++++++------------ 2 files changed, 23 insertions(+), 73 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/FastStoreLoadAnalyzer.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/FastStoreLoadAnalyzer.kt index a8edf156465..66c139639ba 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/FastStoreLoadAnalyzer.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/FastStoreLoadAnalyzer.kt @@ -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 : Interpreter(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 : Interpreter(API_VERSION) -@Suppress("UNCHECKED_CAST") class StoreLoadFrame(val maxLocals: Int) : Frame(maxLocals, 0) { - private val locals = arrayOfNulls(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): StoreLoadFrame { - System.arraycopy(other.locals, 0, this.locals, 0, locals.size) - return this - } - - fun execute(insn: AbstractInsnNode, interpreter: StoreLoadInterpreter) { + override fun execute(insn: AbstractInsnNode, interpreter: Interpreter) { 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, interpreter: StoreLoadInterpreter): 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( @@ -192,7 +157,7 @@ class FastStoreLoadAnalyzer( 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] -> { diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/TemporaryVals.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/TemporaryVals.kt index e52ea9b6c7f..de2924a045f 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/TemporaryVals.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/optimization/temporaryVals/TemporaryVals.kt @@ -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 ) : StoreLoadInterpreter() { - 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?): 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") } } }