JVM minor: extract base class from FixStackInterpreter

This commit is contained in:
Dmitry Petrov
2021-08-13 12:17:34 +03:00
committed by TeamCityServer
parent 4f29c113b7
commit 7b3d5b7863
2 changed files with 192 additions and 136 deletions
@@ -0,0 +1,167 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.codegen.optimization.fixStack
import org.jetbrains.kotlin.codegen.inline.insnOpcodeText
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.org.objectweb.asm.Handle
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
abstract class BasicTypeInterpreter<V : Value> : Interpreter<V>(API_VERSION) {
protected abstract fun uninitializedValue(): V
protected abstract fun booleanValue(): V
protected abstract fun charValue(): V
protected abstract fun byteValue(): V
protected abstract fun shortValue(): V
protected abstract fun intValue(): V
protected abstract fun longValue(): V
protected abstract fun floatValue(): V
protected abstract fun doubleValue(): V
protected abstract fun nullValue(): V
protected abstract fun objectValue(type: Type): V
protected abstract fun arrayValue(type: Type): V
protected abstract fun methodValue(type: Type): V
protected abstract fun handleValue(handle: Handle): V
protected abstract fun typeConstValue(typeConst: Type): V
protected abstract fun aaLoadValue(arrayValue: V): V
override fun newValue(type: Type?): V? =
if (type == null)
uninitializedValue()
else when (type.sort) {
Type.VOID -> null
Type.BOOLEAN -> booleanValue()
Type.CHAR -> charValue()
Type.BYTE -> byteValue()
Type.SHORT -> shortValue()
Type.INT -> intValue()
Type.FLOAT -> floatValue()
Type.LONG -> longValue()
Type.DOUBLE -> doubleValue()
Type.ARRAY -> arrayValue(type)
Type.OBJECT -> objectValue(type)
Type.METHOD -> methodValue(type)
else -> throw AssertionError("Unexpected type: $type")
}
override fun newOperation(insn: AbstractInsnNode): V? =
when (insn.opcode) {
ACONST_NULL ->
nullValue()
ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5 ->
intValue()
LCONST_0, LCONST_1 ->
longValue()
FCONST_0, FCONST_1, FCONST_2 ->
floatValue()
DCONST_0, DCONST_1 ->
doubleValue()
BIPUSH, SIPUSH ->
intValue()
LDC -> {
when (val cst = (insn as LdcInsnNode).cst) {
is Int -> intValue()
is Float -> floatValue()
is Long -> longValue()
is Double -> doubleValue()
is String -> objectValue(AsmTypes.JAVA_STRING_TYPE)
is Handle -> handleValue(cst)
is Type -> typeConstValue(cst)
else -> throw IllegalArgumentException("Illegal LDC constant $cst")
}
}
GETSTATIC ->
newValue(Type.getType((insn as FieldInsnNode).desc))
NEW ->
newValue(Type.getObjectType((insn as TypeInsnNode).desc))
else ->
throw IllegalArgumentException("Unexpected instruction: " + insn.insnOpcodeText)
}
override fun binaryOperation(insn: AbstractInsnNode, value1: V, value2: V): V? =
when (insn.opcode) {
IALOAD, BALOAD, CALOAD, SALOAD, IADD, ISUB, IMUL, IDIV, IREM, ISHL, ISHR, IUSHR, IAND, IOR, IXOR ->
intValue()
FALOAD, FADD, FSUB, FMUL, FDIV, FREM ->
floatValue()
LALOAD, LADD, LSUB, LMUL, LDIV, LREM, LSHL, LSHR, LUSHR, LAND, LOR, LXOR ->
longValue()
DALOAD, DADD, DSUB, DMUL, DDIV, DREM ->
doubleValue()
AALOAD ->
aaLoadValue(value1)
LCMP, FCMPL, FCMPG, DCMPL, DCMPG ->
intValue()
IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, PUTFIELD ->
null
else ->
throw IllegalArgumentException("Unexpected instruction: " + insn.insnOpcodeText)
}
override fun ternaryOperation(insn: AbstractInsnNode, value1: V, value2: V, value3: V): V? =
null
override fun naryOperation(insn: AbstractInsnNode, values: List<V>): V? =
when (insn.opcode) {
MULTIANEWARRAY ->
newValue(Type.getType((insn as MultiANewArrayInsnNode).desc))
INVOKEDYNAMIC ->
newValue(Type.getReturnType((insn as InvokeDynamicInsnNode).desc))
else ->
newValue(Type.getReturnType((insn as MethodInsnNode).desc))
}
override fun returnOperation(insn: AbstractInsnNode, value: V?, expected: V?) {
}
override fun unaryOperation(insn: AbstractInsnNode, value: V): V? =
when (insn.opcode) {
INEG, IINC, L2I, F2I, D2I, I2B, I2C, I2S ->
intValue()
FNEG, I2F, L2F, D2F ->
floatValue()
LNEG, I2L, F2L, D2L ->
longValue()
DNEG, I2D, L2D, F2D ->
doubleValue()
IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, PUTSTATIC ->
null
GETFIELD ->
newValue(Type.getType((insn as FieldInsnNode).desc))
NEWARRAY ->
when ((insn as IntInsnNode).operand) {
T_BOOLEAN -> newValue(Type.getType("[Z"))
T_CHAR -> newValue(Type.getType("[C"))
T_BYTE -> newValue(Type.getType("[B"))
T_SHORT -> newValue(Type.getType("[S"))
T_INT -> newValue(Type.getType("[I"))
T_FLOAT -> newValue(Type.getType("[F"))
T_DOUBLE -> newValue(Type.getType("[D"))
T_LONG -> newValue(Type.getType("[J"))
else -> throw AnalyzerException(insn, "Invalid array type")
}
ANEWARRAY ->
newValue(Type.getType("[" + Type.getObjectType((insn as TypeInsnNode).desc)))
ARRAYLENGTH ->
intValue()
ATHROW ->
null
CHECKCAST ->
newValue(Type.getObjectType((insn as TypeInsnNode).desc))
INSTANCEOF ->
intValue()
MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL ->
null
else ->
throw IllegalArgumentException("Unexpected instruction: " + insn.insnOpcodeText)
}
}
@@ -5,153 +5,42 @@
package org.jetbrains.kotlin.codegen.optimization.fixStack
import org.jetbrains.kotlin.codegen.inline.insnOpcodeText
import org.jetbrains.org.objectweb.asm.Handle
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
open class FixStackInterpreter : Interpreter<FixStackValue>(API_VERSION) {
class FixStackInterpreter : BasicTypeInterpreter<FixStackValue>() {
override fun uninitializedValue() = FixStackValue.UNINITIALIZED
override fun booleanValue() = FixStackValue.INT
override fun charValue() = FixStackValue.INT
override fun byteValue() = FixStackValue.INT
override fun shortValue() = FixStackValue.INT
override fun intValue() = FixStackValue.INT
override fun longValue() = FixStackValue.LONG
override fun floatValue() = FixStackValue.FLOAT
override fun doubleValue() = FixStackValue.DOUBLE
override fun nullValue() = FixStackValue.OBJECT
override fun objectValue(type: Type) = FixStackValue.OBJECT
override fun arrayValue(type: Type) = FixStackValue.OBJECT
override fun methodValue(type: Type) = FixStackValue.OBJECT
override fun handleValue(handle: Handle) = FixStackValue.OBJECT
override fun typeConstValue(typeConst: Type) = FixStackValue.OBJECT
override fun aaLoadValue(arrayValue: FixStackValue) = FixStackValue.OBJECT
override fun newValue(type: Type?): FixStackValue =
type?.toFixStackValue()
?: FixStackValue.UNINITIALIZED
override fun newOperation(insn: AbstractInsnNode): FixStackValue? =
when (insn.opcode) {
ACONST_NULL ->
FixStackValue.OBJECT
ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5 ->
FixStackValue.INT
LCONST_0, LCONST_1 ->
FixStackValue.LONG
FCONST_0, FCONST_1, FCONST_2 ->
FixStackValue.FLOAT
DCONST_0, DCONST_1 ->
FixStackValue.DOUBLE
BIPUSH, SIPUSH ->
FixStackValue.INT
LDC -> {
when (val cst = (insn as LdcInsnNode).cst) {
is Int ->
FixStackValue.INT
is Float ->
FixStackValue.FLOAT
is Long ->
FixStackValue.LONG
is Double ->
FixStackValue.DOUBLE
is String, is Handle ->
FixStackValue.OBJECT
is Type -> {
val sort = cst.sort
if (sort == Type.OBJECT || sort == Type.ARRAY || sort == Type.METHOD)
FixStackValue.OBJECT
else
throw IllegalArgumentException("Illegal LDC constant $cst")
}
else ->
throw IllegalArgumentException("Illegal LDC constant $cst")
}
}
GETSTATIC ->
newValue(Type.getType((insn as FieldInsnNode).desc))
NEW ->
newValue(Type.getObjectType((insn as TypeInsnNode).desc))
else ->
throw IllegalArgumentException("Unexpected instruction: " + insn.insnOpcodeText)
}
override fun copyOperation(insn: AbstractInsnNode, value: FixStackValue?): FixStackValue =
override fun copyOperation(insn: AbstractInsnNode, value: FixStackValue): FixStackValue =
when (insn.opcode) {
ILOAD -> FixStackValue.INT
LLOAD -> FixStackValue.LONG
FLOAD -> FixStackValue.FLOAT
DLOAD -> FixStackValue.DOUBLE
ALOAD -> FixStackValue.OBJECT
else -> value!!
else -> value
}
override fun binaryOperation(insn: AbstractInsnNode, value1: FixStackValue?, value2: FixStackValue?): FixStackValue? =
when (insn.opcode) {
IALOAD, BALOAD, CALOAD, SALOAD, IADD, ISUB, IMUL, IDIV, IREM, ISHL, ISHR, IUSHR, IAND, IOR, IXOR ->
FixStackValue.INT
FALOAD, FADD, FSUB, FMUL, FDIV, FREM ->
FixStackValue.FLOAT
LALOAD, LADD, LSUB, LMUL, LDIV, LREM, LSHL, LSHR, LUSHR, LAND, LOR, LXOR ->
FixStackValue.LONG
DALOAD, DADD, DSUB, DMUL, DDIV, DREM ->
FixStackValue.DOUBLE
AALOAD ->
FixStackValue.OBJECT
LCMP, FCMPL, FCMPG, DCMPL, DCMPG ->
FixStackValue.INT
IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, PUTFIELD ->
null
else ->
throw IllegalArgumentException("Unexpected instruction: " + insn.insnOpcodeText)
}
override fun ternaryOperation(
insn: AbstractInsnNode,
value1: FixStackValue?,
value2: FixStackValue?,
value3: FixStackValue?
): FixStackValue? =
null
override fun naryOperation(insn: AbstractInsnNode, values: List<FixStackValue?>): FixStackValue? =
when (insn.opcode) {
MULTIANEWARRAY ->
newValue(Type.getType((insn as MultiANewArrayInsnNode).desc))
INVOKEDYNAMIC ->
newValue(Type.getReturnType((insn as InvokeDynamicInsnNode).desc))
else ->
newValue(Type.getReturnType((insn as MethodInsnNode).desc))
}
override fun returnOperation(insn: AbstractInsnNode?, value: FixStackValue?, expected: FixStackValue?) {
}
override fun unaryOperation(insn: AbstractInsnNode, value: FixStackValue?): FixStackValue? =
when (insn.opcode) {
INEG, IINC, L2I, F2I, D2I, I2B, I2C, I2S ->
FixStackValue.INT
FNEG, I2F, L2F, D2F ->
FixStackValue.FLOAT
LNEG, I2L, F2L, D2L ->
FixStackValue.LONG
DNEG, I2D, L2D, F2D ->
FixStackValue.DOUBLE
IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, PUTSTATIC ->
null
GETFIELD ->
newValue(Type.getType((insn as FieldInsnNode).desc))
NEWARRAY ->
FixStackValue.OBJECT
ANEWARRAY -> {
FixStackValue.OBJECT
}
ARRAYLENGTH ->
FixStackValue.INT
ATHROW ->
null
CHECKCAST ->
FixStackValue.OBJECT
INSTANCEOF ->
FixStackValue.INT
MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL ->
null
else ->
throw IllegalArgumentException("Unexpected instruction: " + insn.insnOpcodeText)
}
override fun merge(v: FixStackValue?, w: FixStackValue?): FixStackValue? =
when {
v == w -> v
v == null -> w
w == null -> v
else -> throw AssertionError("Mismatching value kinds: $v != $w")
}
override fun merge(v: FixStackValue, w: FixStackValue): FixStackValue =
if (v == w)
v
else
throw AssertionError("Mismatching value kinds: $v != $w")
}