JVM minor: extract base class from FixStackInterpreter
This commit is contained in:
committed by
TeamCityServer
parent
4f29c113b7
commit
7b3d5b7863
+167
@@ -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)
|
||||||
|
}
|
||||||
|
}
|
||||||
+25
-136
@@ -5,153 +5,42 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.optimization.fixStack
|
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.Handle
|
||||||
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.*
|
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
|
|
||||||
|
|
||||||
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 =
|
override fun copyOperation(insn: AbstractInsnNode, value: FixStackValue): 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 =
|
|
||||||
when (insn.opcode) {
|
when (insn.opcode) {
|
||||||
ILOAD -> FixStackValue.INT
|
ILOAD -> FixStackValue.INT
|
||||||
LLOAD -> FixStackValue.LONG
|
LLOAD -> FixStackValue.LONG
|
||||||
FLOAD -> FixStackValue.FLOAT
|
FLOAD -> FixStackValue.FLOAT
|
||||||
DLOAD -> FixStackValue.DOUBLE
|
DLOAD -> FixStackValue.DOUBLE
|
||||||
ALOAD -> FixStackValue.OBJECT
|
ALOAD -> FixStackValue.OBJECT
|
||||||
else -> value!!
|
else -> value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun binaryOperation(insn: AbstractInsnNode, value1: FixStackValue?, value2: FixStackValue?): FixStackValue? =
|
override fun merge(v: FixStackValue, w: FixStackValue): FixStackValue =
|
||||||
when (insn.opcode) {
|
if (v == w)
|
||||||
IALOAD, BALOAD, CALOAD, SALOAD, IADD, ISUB, IMUL, IDIV, IREM, ISHL, ISHR, IUSHR, IAND, IOR, IXOR ->
|
v
|
||||||
FixStackValue.INT
|
else
|
||||||
FALOAD, FADD, FSUB, FMUL, FDIV, FREM ->
|
throw AssertionError("Mismatching value kinds: $v != $w")
|
||||||
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")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user