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
|
||||
|
||||
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")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user