Control logic will be handled by interpreter loop

This commit is contained in:
Andrey Breslav
2013-10-06 13:22:16 +04:00
parent 21e0dabf87
commit f93d209b88
+34 -33
View File
@@ -38,14 +38,7 @@ trait Eval {
fun invokeMethod(instance: Value, methodDesc: String, arguments: List<Value>, invokespecial: Boolean = false): Value
}
trait Control {
fun jump(label: LabelNode)
fun returnValue(value: Value)
fun throwException(value: Value)
}
class SingleInstructionInterpreter(private val eval: Eval, private val control: Control) : Interpreter<Value>(ASM4) {
class SingleInstructionInterpreter(private val eval: Eval) : Interpreter<Value>(ASM4) {
override fun newValue(`type`: Type?): Value? {
if (`type` == null) {
return NOT_A_VALUE
@@ -141,17 +134,7 @@ class SingleInstructionInterpreter(private val eval: Eval, private val control:
F2D -> double(value.float.toDouble())
IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IFNULL, IFNONNULL -> {
val label = (insn as JumpInsnNode).label
when (insn.getOpcode()) {
IFEQ -> if (value.int == 0) control.jump(label)
IFNE -> if (value.int != 0) control.jump(label)
IFLT -> if (value.int < 0) control.jump(label)
IFGT -> if (value.int > 0) control.jump(label)
IFLE -> if (value.int <= 0) control.jump(label)
IFGE -> if (value.int >= 0) control.jump(label)
IFNULL -> if (value.obj == null) control.jump(label)
IFNONNULL -> if (value.obj != null) control.jump(label)
}
// Handled by interpreter loop, see checkUnaryCondition()
null
}
@@ -187,7 +170,7 @@ class SingleInstructionInterpreter(private val eval: Eval, private val control:
ARRAYLENGTH -> eval.getArrayLength(value)
ATHROW -> {
control.throwException(value)
// Handled by interpreter loop
null
}
@@ -208,6 +191,20 @@ class SingleInstructionInterpreter(private val eval: Eval, private val control:
}
}
public fun checkUnaryCondition(value: Value, opcode: Int): Boolean {
return when (opcode) {
IFEQ -> value.int == 0
IFNE -> value.int != 0
IFLT -> value.int < 0
IFGT -> value.int > 0
IFLE -> value.int <= 0
IFGE -> value.int >= 0
IFNULL -> value.obj == null
IFNONNULL -> value.obj != null
else -> throw UnsupportedByteCodeException("Unknown opcode: $opcode")
}
}
override fun binaryOperation(insn: AbstractInsnNode, value1: Value, value2: Value): Value? {
return when (insn.getOpcode()) {
IALOAD, BALOAD, CALOAD, SALOAD,
@@ -290,18 +287,7 @@ class SingleInstructionInterpreter(private val eval: Eval, private val control:
}
IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE -> {
val label = (insn as JumpInsnNode).label
when (insn.getOpcode()) {
IF_ICMPEQ -> if (value1.int == value2.int) control.jump(label)
IF_ICMPNE -> if (value1.int != value2.int) control.jump(label)
IF_ICMPLT -> if (value1.int < value2.int) control.jump(label)
IF_ICMPGT -> if (value1.int > value2.int) control.jump(label)
IF_ICMPLE -> if (value1.int <= value2.int) control.jump(label)
IF_ICMPGE -> if (value1.int >= value2.int) control.jump(label)
IF_ACMPEQ -> if (value1.obj == value2.obj) control.jump(label)
IF_ACMPNE -> if (value1.obj != value2.obj) control.jump(label)
}
// Handled by interpreter loop, see checkBinaryCondition()
null
}
@@ -314,6 +300,21 @@ class SingleInstructionInterpreter(private val eval: Eval, private val control:
}
}
public fun checkBinaryCondition(value1: Value, value2: Value, opcode: Int): Boolean {
return when (opcode) {
IF_ICMPEQ -> value1.int == value2.int
IF_ICMPNE -> value1.int != value2.int
IF_ICMPLT -> value1.int < value2.int
IF_ICMPGT -> value1.int > value2.int
IF_ICMPLE -> value1.int <= value2.int
IF_ICMPGE -> value1.int >= value2.int
IF_ACMPEQ -> value1.obj == value2.obj
IF_ACMPNE -> value1.obj != value2.obj
else -> throw UnsupportedByteCodeException("Unknown opcode: $opcode")
}
}
override fun ternaryOperation(insn: AbstractInsnNode, value1: Value, value2: Value, value3: Value): Value? {
return when (insn.getOpcode()) {
IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE -> {
@@ -357,7 +358,7 @@ class SingleInstructionInterpreter(private val eval: Eval, private val control:
DRETURN,
ARETURN -> {
// TODO: coercion, maybe?
control.returnValue(value)
// Handled by interpreter loop
}
else -> throw UnsupportedByteCodeException("$insn")