Start with initial frame, not from scratch
This commit is contained in:
@@ -48,8 +48,8 @@ trait InterpretationEventHandler {
|
|||||||
class ThrownFromEvalException(val exception: Value): RuntimeException()
|
class ThrownFromEvalException(val exception: Value): RuntimeException()
|
||||||
|
|
||||||
fun interpreterLoop(
|
fun interpreterLoop(
|
||||||
ownerClassInternalName: String,
|
|
||||||
m: MethodNode,
|
m: MethodNode,
|
||||||
|
initialState: Frame<Value>,
|
||||||
eval: Eval,
|
eval: Eval,
|
||||||
handler: InterpretationEventHandler = InterpretationEventHandler.NONE
|
handler: InterpretationEventHandler = InterpretationEventHandler.NONE
|
||||||
): InterpreterResult {
|
): InterpreterResult {
|
||||||
@@ -64,7 +64,7 @@ fun interpreterLoop(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val interpreter = SingleInstructionInterpreter(eval)
|
val interpreter = SingleInstructionInterpreter(eval)
|
||||||
val frame = initFrame(ownerClassInternalName, m, interpreter)
|
val frame = Frame(initialState)
|
||||||
val handlers = computeHandlers(m)
|
val handlers = computeHandlers(m)
|
||||||
|
|
||||||
class ResultException(val result: InterpreterResult): RuntimeException()
|
class ResultException(val result: InterpreterResult): RuntimeException()
|
||||||
@@ -193,35 +193,6 @@ fun interpreterLoop(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Copied from org.objectweb.asm.tree.analysis.Analyzer.analyze()
|
// Copied from org.objectweb.asm.tree.analysis.Analyzer.analyze()
|
||||||
fun <V : org.objectweb.asm.tree.analysis.Value> initFrame(
|
|
||||||
owner: String,
|
|
||||||
m: MethodNode,
|
|
||||||
interpreter: Interpreter<V>
|
|
||||||
): Frame<V> {
|
|
||||||
val current = Frame<V>(m.maxLocals, m.maxStack)
|
|
||||||
current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)))
|
|
||||||
|
|
||||||
var local = 0
|
|
||||||
if ((m.access and ACC_STATIC) == 0) {
|
|
||||||
val ctype = Type.getObjectType(owner)
|
|
||||||
current.setLocal(local++, interpreter.newValue(ctype))
|
|
||||||
}
|
|
||||||
|
|
||||||
val args = Type.getArgumentTypes(m.desc)
|
|
||||||
for (i in 0..args.size - 1) {
|
|
||||||
current.setLocal(local++, interpreter.newValue(args[i]))
|
|
||||||
if (args[i].getSize() == 2) {
|
|
||||||
current.setLocal(local++, interpreter.newValue(null))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (local < m.maxLocals) {
|
|
||||||
current.setLocal(local++, interpreter.newValue(null))
|
|
||||||
}
|
|
||||||
|
|
||||||
return current
|
|
||||||
}
|
|
||||||
|
|
||||||
fun computeHandlers(m: MethodNode): Array<out List<TryCatchBlockNode>?> {
|
fun computeHandlers(m: MethodNode): Array<out List<TryCatchBlockNode>?> {
|
||||||
val insns = m.instructions
|
val insns = m.instructions
|
||||||
val handlers = Array<MutableList<TryCatchBlockNode>?>(insns.size()) {null}
|
val handlers = Array<MutableList<TryCatchBlockNode>?>(insns.size()) {null}
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import java.lang.reflect.Field
|
|||||||
import java.lang.reflect.Constructor
|
import java.lang.reflect.Constructor
|
||||||
import java.lang.reflect.InvocationTargetException
|
import java.lang.reflect.InvocationTargetException
|
||||||
import java.lang.reflect.Array as JArray
|
import java.lang.reflect.Array as JArray
|
||||||
|
import org.objectweb.asm.tree.analysis.Interpreter
|
||||||
|
import org.objectweb.asm.tree.analysis.Frame
|
||||||
|
|
||||||
fun suite(): TestSuite {
|
fun suite(): TestSuite {
|
||||||
val suite = TestSuite()
|
val suite = TestSuite()
|
||||||
@@ -72,8 +74,12 @@ fun doTest(ownerClass: Class<TestData>, methodNode: MethodNode): TestCase? {
|
|||||||
|
|
||||||
override fun runTest() {
|
override fun runTest() {
|
||||||
val value = interpreterLoop(
|
val value = interpreterLoop(
|
||||||
ownerClass.getInternalName(),
|
|
||||||
methodNode,
|
methodNode,
|
||||||
|
initFrame(
|
||||||
|
ownerClass.getInternalName(),
|
||||||
|
methodNode,
|
||||||
|
SingleInstructionInterpreter(REFLECTION_EVAL)
|
||||||
|
),
|
||||||
REFLECTION_EVAL
|
REFLECTION_EVAL
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -82,6 +88,35 @@ fun doTest(ownerClass: Class<TestData>, methodNode: MethodNode): TestCase? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <V : org.objectweb.asm.tree.analysis.Value> initFrame(
|
||||||
|
owner: String,
|
||||||
|
m: MethodNode,
|
||||||
|
interpreter: Interpreter<V>
|
||||||
|
): Frame<V> {
|
||||||
|
val current = Frame<V>(m.maxLocals, m.maxStack)
|
||||||
|
current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)))
|
||||||
|
|
||||||
|
var local = 0
|
||||||
|
if ((m.access and ACC_STATIC) == 0) {
|
||||||
|
val ctype = Type.getObjectType(owner)
|
||||||
|
current.setLocal(local++, interpreter.newValue(ctype))
|
||||||
|
}
|
||||||
|
|
||||||
|
val args = Type.getArgumentTypes(m.desc)
|
||||||
|
for (i in 0..args.size - 1) {
|
||||||
|
current.setLocal(local++, interpreter.newValue(args[i]))
|
||||||
|
if (args[i].getSize() == 2) {
|
||||||
|
current.setLocal(local++, interpreter.newValue(null))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (local < m.maxLocals) {
|
||||||
|
current.setLocal(local++, interpreter.newValue(null))
|
||||||
|
}
|
||||||
|
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
|
||||||
fun objectToValue(obj: Any?, expectedType: Type): Value {
|
fun objectToValue(obj: Any?, expectedType: Type): Value {
|
||||||
return when (expectedType.getSort()) {
|
return when (expectedType.getSort()) {
|
||||||
Type.VOID -> VOID_VALUE
|
Type.VOID -> VOID_VALUE
|
||||||
|
|||||||
Reference in New Issue
Block a user