From 5c02a91a35e3d7ee759ca8911a866adc8e1e4ff4 Mon Sep 17 00:00:00 2001 From: jochen Date: Fri, 9 Apr 1999 08:07:51 +0000 Subject: [PATCH] Many clean ups, use RuntimeException note that there is also a jasmin implementation git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@538 379699f6-c40d-0410-875b-85095c16579e --- jode/jode/jvm/Interpreter.java | 1333 +++++++++++++++----------------- 1 file changed, 641 insertions(+), 692 deletions(-) diff --git a/jode/jode/jvm/Interpreter.java b/jode/jode/jvm/Interpreter.java index f7401b9..bbc8ea0 100644 --- a/jode/jode/jvm/Interpreter.java +++ b/jode/jode/jvm/Interpreter.java @@ -21,7 +21,8 @@ package jode.jvm; import jode.*; import jode.bytecode.*; import jode.decompiler.ClassAnalyzer; -import java.lang.reflect.*; +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; /** * This class is a java virtual machine written in java :-). Well not @@ -32,742 +33,690 @@ import java.lang.reflect.*; */ public class Interpreter implements Opcodes { - static boolean checkType(Type type1, Class type2) { - if (type1 == Type.tBoolean) { - return type2 == Boolean.TYPE; - } else if (type1 == Type.tByte) { - return type2 == Byte.TYPE; - } else if (type1 == Type.tChar) { - return type2 == Character.TYPE; - } else if (type1 == Type.tShort) { - return type2 == Short.TYPE; - } else if (type1 == Type.tInt) { - return type2 == Integer.TYPE; - } else if (type1 == Type.tLong) { - return type2 == Long.TYPE; - } else if (type1 == Type.tFloat) { - return type2 == Float.TYPE; - } else if (type1 == Type.tDouble) { - return type2 == Double.TYPE; - } else if (type1 == Type.tVoid) { - return type2 == Void.TYPE; - } else if (type1 instanceof ArrayType) { - if (!type2.isArray()) - return false; - return checkType(((ArrayType)type1).getElementType(), - type2.getComponentType()); - } else if (type1 instanceof ClassInterfacesType) { - return type1.equals(Type.tClass(type2.getName())); - } else - return false; - } - - static boolean checkMethod(MethodType methodType, - Class[] paramTypes, Class retType) { - Type[] params = methodType.getParameterTypes(); - if (params.length != paramTypes.length) - return false; - for (int i=0; i < params.length; i++) { - if (!checkType(params[i], paramTypes[i])) - return false; - } - return checkType(methodType.getReturnType(), retType); - } - public static Object interpretMethod - (ClassAnalyzer ca, BytecodeInfo code, Value[] locals, Value[] stack) - throws InterpreterException, ClassFormatException { - try { + (RuntimeEnvironment env, BytecodeInfo code, Value[] locals) + throws InterpreterException, InvocationTargetException { + Value[] stack = new Value[code.getMaxStack()]; + for (int i=0; i< stack.length; i++) + stack[i] = new Value(); + Instruction pc = code.getFirstInstr(); int stacktop = 0; + big_loop: for(;;) { - Instruction instr = pc; -// System.err.print(instr.addr+": ["); -// for (int i=0; i0) -// System.err.print(","); -// System.err.print(stack[i]); -// if (stack[i].objectValue() instanceof char[]) { -// System.err.print(new String((char[])stack[i].objectValue())); -// } -// } -// System.err.println("]"); -// System.err.print("local: ["); -// for (int i=0; i0) + System.err.print(","); + System.err.print(stack[i]); + if (stack[i].objectValue() instanceof char[]) { + System.err.print(new String((char[])stack[i].objectValue())); + } + } + System.err.println("]"); + System.err.print("local: ["); + for (int i=0; i> stack[stacktop-1].intValue()); - stacktop--; - break; - case opc_iushr: - stack[stacktop-2].setInt(stack[stacktop-2].intValue() - >>> stack[stacktop-1].intValue()); - stacktop--; - break; - case opc_iand: - stack[stacktop-2].setInt(stack[stacktop-2].intValue() - & stack[stacktop-1].intValue()); - stacktop--; - break; - case opc_ior : - stack[stacktop-2].setInt(stack[stacktop-2].intValue() - | stack[stacktop-1].intValue()); - stacktop--; - break; - case opc_ixor: - stack[stacktop-2].setInt(stack[stacktop-2].intValue() - ^ stack[stacktop-1].intValue()); - stacktop--; - break; + case opc_ishl: + stack[stacktop-2].setInt(stack[stacktop-2].intValue() + << stack[stacktop-1].intValue()); + stacktop--; + break; + case opc_ishr: + stack[stacktop-2].setInt(stack[stacktop-2].intValue() + >> stack[stacktop-1].intValue()); + stacktop--; + break; + case opc_iushr: + stack[stacktop-2].setInt(stack[stacktop-2].intValue() + >>> stack[stacktop-1].intValue()); + stacktop--; + break; + case opc_iand: + stack[stacktop-2].setInt(stack[stacktop-2].intValue() + & stack[stacktop-1].intValue()); + stacktop--; + break; + case opc_ior : + stack[stacktop-2].setInt(stack[stacktop-2].intValue() + | stack[stacktop-1].intValue()); + stacktop--; + break; + case opc_ixor: + stack[stacktop-2].setInt(stack[stacktop-2].intValue() + ^ stack[stacktop-1].intValue()); + stacktop--; + break; - case opc_lshl: - stack[stacktop-2].setLong(stack[stacktop-2].longValue() - << stack[stacktop-1].longValue()); - stacktop--; - break; - case opc_lshr: - stack[stacktop-2].setLong(stack[stacktop-2].longValue() - >> stack[stacktop-1].longValue()); - stacktop--; - break; - case opc_lushr: - stack[stacktop-2].setLong(stack[stacktop-2].longValue() - >>> stack[stacktop-1].longValue()); - stacktop--; - break; - case opc_land: - stack[stacktop-2].setLong(stack[stacktop-2].longValue() - & stack[stacktop-1].longValue()); - stacktop--; - break; - case opc_lor : - stack[stacktop-2].setLong(stack[stacktop-2].longValue() - | stack[stacktop-1].longValue()); - stacktop--; - break; - case opc_lxor: - stack[stacktop-2].setLong(stack[stacktop-2].longValue() - ^ stack[stacktop-1].longValue()); - stacktop--; - break; + case opc_lshl: + stack[stacktop-2].setLong(stack[stacktop-2].longValue() + << stack[stacktop-1].longValue()); + stacktop--; + break; + case opc_lshr: + stack[stacktop-2].setLong(stack[stacktop-2].longValue() + >> stack[stacktop-1].longValue()); + stacktop--; + break; + case opc_lushr: + stack[stacktop-2].setLong(stack[stacktop-2].longValue() + >>> stack[stacktop-1].longValue()); + stacktop--; + break; + case opc_land: + stack[stacktop-2].setLong(stack[stacktop-2].longValue() + & stack[stacktop-1].longValue()); + stacktop--; + break; + case opc_lor : + stack[stacktop-2].setLong(stack[stacktop-2].longValue() + | stack[stacktop-1].longValue()); + stacktop--; + break; + case opc_lxor: + stack[stacktop-2].setLong(stack[stacktop-2].longValue() + ^ stack[stacktop-1].longValue()); + stacktop--; + break; - case opc_iinc: - locals[instr.localSlot].setInt - (locals[instr.localSlot].intValue() + instr.intData); - break; - case opc_i2l: - stack[stacktop-1] - .setLong((long)stack[stacktop-1].intValue()); - break; - case opc_i2f: - stack[stacktop-1] - .setFloat((float)stack[stacktop-1].intValue()); - break; - case opc_i2d: - stack[stacktop-1] - .setDouble((double)stack[stacktop-1].intValue()); - break; + case opc_iinc: + locals[instr.localSlot].setInt + (locals[instr.localSlot].intValue() + instr.intData); + break; + case opc_i2l: + stack[stacktop-1] + .setLong((long)stack[stacktop-1].intValue()); + break; + case opc_i2f: + stack[stacktop-1] + .setFloat((float)stack[stacktop-1].intValue()); + break; + case opc_i2d: + stack[stacktop-1] + .setDouble((double)stack[stacktop-1].intValue()); + break; - case opc_l2i: - stack[stacktop-1] - .setInt((int)stack[stacktop-1].longValue()); - break; - case opc_l2f: - stack[stacktop-1] - .setFloat((float)stack[stacktop-1].longValue()); - break; - case opc_l2d: - stack[stacktop-1] - .setDouble((double)stack[stacktop-1].longValue()); - break; + case opc_l2i: + stack[stacktop-1] + .setInt((int)stack[stacktop-1].longValue()); + break; + case opc_l2f: + stack[stacktop-1] + .setFloat((float)stack[stacktop-1].longValue()); + break; + case opc_l2d: + stack[stacktop-1] + .setDouble((double)stack[stacktop-1].longValue()); + break; - case opc_f2i: - stack[stacktop-1] - .setInt((int)stack[stacktop-1].floatValue()); - break; - case opc_f2l: - stack[stacktop-1] - .setLong((long)stack[stacktop-1].floatValue()); - break; - case opc_f2d: - stack[stacktop-1] - .setDouble((double)stack[stacktop-1].floatValue()); - break; + case opc_f2i: + stack[stacktop-1] + .setInt((int)stack[stacktop-1].floatValue()); + break; + case opc_f2l: + stack[stacktop-1] + .setLong((long)stack[stacktop-1].floatValue()); + break; + case opc_f2d: + stack[stacktop-1] + .setDouble((double)stack[stacktop-1].floatValue()); + break; - case opc_d2i: - stack[stacktop-1] - .setInt((int)stack[stacktop-1].doubleValue()); - break; - case opc_d2l: - stack[stacktop-1] - .setLong((long)stack[stacktop-1].doubleValue()); - break; - case opc_d2f: - stack[stacktop-1] - .setFloat((float)stack[stacktop-1].doubleValue()); - break; + case opc_d2i: + stack[stacktop-1] + .setInt((int)stack[stacktop-1].doubleValue()); + break; + case opc_d2l: + stack[stacktop-1] + .setLong((long)stack[stacktop-1].doubleValue()); + break; + case opc_d2f: + stack[stacktop-1] + .setFloat((float)stack[stacktop-1].doubleValue()); + break; - case opc_i2b: - stack[stacktop-1] - .setInt((byte)stack[stacktop-1].intValue()); - break; - case opc_i2c: - stack[stacktop-1] - .setInt((char)stack[stacktop-1].intValue()); - break; - case opc_i2s: - stack[stacktop-1] - .setInt((short)stack[stacktop-1].intValue()); - break; - case opc_lcmp: { - long val1 = stack[stacktop-2].longValue(); - long val2 = stack[--stacktop].longValue(); - stack[stacktop-1].setInt - (val1 == val2 ? 0 : val1 < val2 ? -1 : 1); - break; - } - case opc_fcmpl: case opc_fcmpg: { - float val1 = stack[stacktop-2].floatValue(); - float val2 = stack[--stacktop].floatValue(); - stack[stacktop-1].setInt - (val1 == val2 ? 0 - : ( opcode == opc_fcmpg - ? (val1 < val2 ? -1 : 1) - : (val1 > val2 ? 1 : -1))); - break; - } - case opc_dcmpl: case opc_dcmpg: { - double val1 = stack[stacktop-2].doubleValue(); - double val2 = stack[--stacktop].doubleValue(); - stack[stacktop-1].setInt - (val1 == val2 ? 0 - : ( opcode == opc_dcmpg - ? (val1 < val2 ? -1 : 1) - : (val1 > val2 ? 1 : -1))); - break; - } - case opc_ifeq: case opc_ifne: - case opc_iflt: case opc_ifge: - case opc_ifgt: case opc_ifle: - case opc_if_icmpeq: case opc_if_icmpne: - case opc_if_icmplt: case opc_if_icmpge: - case opc_if_icmpgt: case opc_if_icmple: - case opc_if_acmpeq: case opc_if_acmpne: - case opc_ifnull: case opc_ifnonnull: { - int value; - if (opcode >= opc_if_acmpeq) { - if (opcode >= opc_ifnull) { - value = - stack[--stacktop].objectValue() == null ? 0 : 1; - opcode += opc_ifeq - opc_ifnull; + case opc_i2b: + stack[stacktop-1] + .setInt((byte)stack[stacktop-1].intValue()); + break; + case opc_i2c: + stack[stacktop-1] + .setInt((char)stack[stacktop-1].intValue()); + break; + case opc_i2s: + stack[stacktop-1] + .setInt((short)stack[stacktop-1].intValue()); + break; + case opc_lcmp: { + long val1 = stack[stacktop-2].longValue(); + long val2 = stack[--stacktop].longValue(); + stack[stacktop-1].setInt + (val1 == val2 ? 0 : val1 < val2 ? -1 : 1); + break; + } + case opc_fcmpl: case opc_fcmpg: { + float val1 = stack[stacktop-2].floatValue(); + float val2 = stack[--stacktop].floatValue(); + stack[stacktop-1].setInt + (val1 == val2 ? 0 + : ( opcode == opc_fcmpg + ? (val1 < val2 ? -1 : 1) + : (val1 > val2 ? 1 : -1))); + break; + } + case opc_dcmpl: case opc_dcmpg: { + double val1 = stack[stacktop-2].doubleValue(); + double val2 = stack[--stacktop].doubleValue(); + stack[stacktop-1].setInt + (val1 == val2 ? 0 + : ( opcode == opc_dcmpg + ? (val1 < val2 ? -1 : 1) + : (val1 > val2 ? 1 : -1))); + break; + } + case opc_ifeq: case opc_ifne: + case opc_iflt: case opc_ifge: + case opc_ifgt: case opc_ifle: + case opc_if_icmpeq: case opc_if_icmpne: + case opc_if_icmplt: case opc_if_icmpge: + case opc_if_icmpgt: case opc_if_icmple: + case opc_if_acmpeq: case opc_if_acmpne: + case opc_ifnull: case opc_ifnonnull: { + int value; + if (opcode >= opc_if_acmpeq) { + if (opcode >= opc_ifnull) { + value = + stack[--stacktop].objectValue() == null ? 0 : 1; + opcode += opc_ifeq - opc_ifnull; + } else { + value = + stack[--stacktop].objectValue() + == stack[--stacktop].objectValue() ? 0 : 1; + opcode += opc_ifeq - opc_if_acmpeq; + } } else { - value = - stack[--stacktop].objectValue() - == stack[--stacktop].objectValue() ? 0 : 1; - opcode += opc_ifeq - opc_if_acmpeq; - } - } else { - value = stack[--stacktop].intValue(); - if (opcode >= opc_if_icmpeq) { - int val1 = stack[--stacktop].intValue(); - value = (val1 == value ? 0 - : val1 < value ? -1 : 1); - opcode += opc_ifeq - opc_if_icmpeq; + value = stack[--stacktop].intValue(); + if (opcode >= opc_if_icmpeq) { + int val1 = stack[--stacktop].intValue(); + value = (val1 == value ? 0 + : val1 < value ? -1 : 1); + opcode += opc_ifeq - opc_if_icmpeq; + } } + if (value > 0 && (opcode == opc_ifgt || opcode == opc_ifge) + || value < 0 && (opcode == opc_iflt || opcode == opc_ifle) + || value == 0 && (opcode == opc_ifge || opcode == opc_ifle + || opcode == opc_ifeq)) + pc = instr.succs[0]; + break; } - if (value > 0 && (opcode == opc_ifgt || opcode == opc_ifge) - || value < 0 && (opcode == opc_iflt || opcode == opc_ifle) - || value == 0 && (opcode == opc_ifge || opcode == opc_ifle - || opcode == opc_ifeq)) + case opc_jsr: + case opc_jsr_w: + stack[stacktop++].setObject(instr); + /* fall through */ + case opc_goto: + case opc_goto_w: pc = instr.succs[0]; - break; - } - case opc_jsr: - case opc_jsr_w: - stack[stacktop++].setObject(instr); - /* fall through */ - case opc_goto: - case opc_goto_w: - pc = instr.succs[0]; - break; - case opc_ret: - pc = (Instruction)locals[instr.localSlot].objectValue(); - break; - case opc_tableswitch: { - int value = stack[--stacktop].intValue(); - int low = instr.intData; - if (value >= low && value <= low + instr.succs.length - 2) - pc = instr.succs[value - low]; - else - pc = instr.succs[instr.succs.length-1]; - break; - } - case opc_lookupswitch: { - int value = stack[--stacktop].intValue(); - int[] values = (int[]) instr.objData; - pc = instr.succs[values.length]; - for (int i=0; i< values.length; i++) { - if (values[i] == value) { - pc = instr.succs[i]; - break; - } + break; + case opc_ret: + pc = (Instruction)locals[instr.localSlot].objectValue(); + break; + case opc_tableswitch: { + int value = stack[--stacktop].intValue(); + int low = instr.intData; + if (value >= low && value <= low + instr.succs.length - 2) + pc = instr.succs[value - low]; + else + pc = instr.succs[instr.succs.length-1]; + break; } - break; - } - case opc_ireturn: case opc_lreturn: - case opc_freturn: case opc_dreturn: case opc_areturn: - return stack[--stacktop].objectValue(); - case opc_return: - return Void.TYPE; - case opc_getstatic: - case opc_getfield: - case opc_putstatic: - case opc_putfield: - throw new InterpreterException - ("Implement get/put-static/field?"); - case opc_invokevirtual: - case opc_invokespecial: - case opc_invokestatic : - case opc_invokeinterface: { - Reference ref = (Reference) instr.objData; - - if (ref.getClazz().equals(ca.getClazz().getName())) { - MethodType mt = (MethodType) Type.tType(ref.getType()); - BytecodeInfo info = ca.getMethod(ref.getName(), mt) - .getCode().getBytecodeInfo(); - Value[] newLocals = new Value[info.getMaxLocals()]; - for (int i=0; i< newLocals.length; i++) - newLocals[i] = new Value(); - Value[] newStack = new Value[info.getMaxStack()]; - for (int i=0; i< newStack.length; i++) - newStack[i] = new Value(); - int param = mt.getParameterTypes().length; - int slot = 0; - if (opcode != opc_invokestatic) - newLocals[slot++].setValue(stack[stacktop-param-1]); - for (int i = 0; i < param; i++) { - newLocals[slot].setValue(stack[stacktop-param+i]); - slot += mt.getParameterTypes()[i].stackSize(); - } - Object result = interpretMethod(ca, info, - newLocals, newStack); - if (mt.getReturnType() != Type.tVoid) - stack[stacktop++].setObject(result); - } else { - Class clazz; - try { - clazz = Class.forName(ref.getClazz()); - } catch (ClassNotFoundException ex) { - throw new InterpreterException - ("Class "+ref.getClazz()+" not found"); - } - try { - if (ref.getName().equals("")) { - Constructor[] cs = clazz.getConstructors(); - Constructor c = null; - for (int i=0; i< cs.length; i++) { - if (checkMethod((MethodType) - Type.tType(ref.getType()), - cs[i].getParameterTypes(), - Void.TYPE)) { - c = cs[i]; - break; - } - } - if (c == null) - throw new InterpreterException - ("Constructor " + ref + " not found."); - Object[] args - = new Object[c.getParameterTypes().length]; - for (int i=args.length - 1; i >= 0; i--) - args[i] = stack[--stacktop].objectValue(); - NewObject newObj = stack[--stacktop].getNewObject(); - if (!newObj.getType().equals(ref.getClazz())) - throw new InterpreterException - ("constructor called on wrong type"); - newObj.setObject(c.newInstance(args)); - } else { - Method[] ms = clazz.getMethods(); - Method m = null; - for (int i=0; i< ms.length; i++) { - if (ms[i].getName().equals(ref.getName())) { - if (checkMethod((MethodType) - Type.tType(ref.getType()), - ms[i].getParameterTypes(), - ms[i].getReturnType())) { - m = ms[i]; - break; - } - } - } - if (m == null) - throw new InterpreterException - ("Method " + ref + " not found."); - Object obj = null; - Object[] args - = new Object[m.getParameterTypes().length]; - for (int i=args.length - 1; i >= 0; i--) - args[i] = stack[--stacktop].objectValue(); - if (opcode != opc_invokestatic) - obj = stack[--stacktop].objectValue(); - /* special and constructor? XXX*/ - Object result = m.invoke(obj, args); - if (m.getReturnType() != Void.TYPE) - stack[stacktop++].setObject(result); + case opc_lookupswitch: { + int value = stack[--stacktop].intValue(); + int[] values = (int[]) instr.objData; + pc = instr.succs[values.length]; + for (int i=0; i< values.length; i++) { + if (values[i] == value) { + pc = instr.succs[i]; + break; } - } catch (IllegalAccessException ex) { - throw new InterpreterException - ("Method " + ref + " not accessible"); - } catch (InstantiationException ex) { - throw new InterpreterException - ("InstantiationException in " + ref + "."); - } catch (InvocationTargetException ex) { - throw new InterpreterException - ("Method " + ref + " throwed an exception"); - /*XXX exception handler?*/ } + break; } - break; - } - case opc_new: { - String clazz = (String) instr.objData; - stack[stacktop++].setNewObject(new NewObject(clazz)); - break; - } - case opc_newarray: { - int length = stack[--stacktop].intValue(); - switch (instr.intData) { - case 4: - stack[stacktop++].setObject(new boolean[length]); + case opc_ireturn: case opc_lreturn: + case opc_freturn: case opc_dreturn: case opc_areturn: + return stack[--stacktop].objectValue(); + case opc_return: + return Void.TYPE; + case opc_getstatic: + stack[stacktop++].setObject + (env.getField((Reference) instr.objData, null)); break; - case 5: - stack[stacktop++].setObject(new char[length]); + case opc_getfield: { + Object cls = stack[--stacktop]; + if (cls == null) + throw new InvocationTargetException + (new NullPointerException()); + stack[stacktop++].setObject + (env.getField((Reference) instr.objData, cls)); break; - case 6: - stack[stacktop++].setObject(new float[length]); + } + case opc_putstatic: { + Object value = stack[--stacktop]; + env.putField((Reference) instr.objData, null, value); break; - case 7: - stack[stacktop++].setObject(new double[length]); + } + case opc_putfield: { + Object value = stack[--stacktop]; + Object cls = stack[--stacktop]; + if (cls == null) + throw new InvocationTargetException + (new NullPointerException()); + env.putField((Reference) instr.objData, cls, value); break; - case 8: - stack[stacktop++].setObject(new byte[length]); + } + case opc_invokevirtual: + case opc_invokespecial: + case opc_invokestatic : + case opc_invokeinterface: { + Reference ref = (Reference) instr.objData; + MethodType mt = (MethodType) Type.tType(ref.getType()); + Object[] args = new Object[mt.getParameterTypes().length]; + for (int i=args.length - 1; i >= 0; i--) { + stacktop -= mt.getParameterTypes()[i].stackSize(); + args[i] = stack[stacktop].objectValue(); + } + + Object result = null; + if (ref.getName().equals("")) { + NewObject newObj = stack[--stacktop].getNewObject(); +// if (!newObj.getType().equals(ref.getClazz())) +// throw new InterpreterException +// ("constructor called on wrong type"); + newObj.setObject(env.invokeConstructor(ref, args)); + } else if (opcode == opc_invokestatic) { + result = env.invokeMethod(ref, false, null, args); + } else { + Object cls = stack[--stacktop].objectValue(); + if (cls == null) + throw new InvocationTargetException + (new NullPointerException()); + result = env.invokeMethod + (ref, opcode != opc_invokespecial, cls, args); + } + if (mt.getReturnType() != Type.tVoid) { + stack[stacktop].setObject(result); + stacktop += mt.getReturnType().stackSize(); + } break; - case 9: - stack[stacktop++].setObject(new short[length]); + } + case opc_new: { + String clazz = (String) instr.objData; + stack[stacktop++].setNewObject(new NewObject(clazz)); break; - case 10: - stack[stacktop++].setObject(new int[length]); + } + case opc_newarray: { + int length = stack[--stacktop].intValue(); + try { + switch (instr.intData) { + case 4: + stack[stacktop++].setObject(new boolean[length]); + break; + case 5: + stack[stacktop++].setObject(new char[length]); + break; + case 6: + stack[stacktop++].setObject(new float[length]); + break; + case 7: + stack[stacktop++].setObject(new double[length]); + break; + case 8: + stack[stacktop++].setObject(new byte[length]); + break; + case 9: + stack[stacktop++].setObject(new short[length]); + break; + case 10: + stack[stacktop++].setObject(new int[length]); + break; + case 11: + stack[stacktop++].setObject(new long[length]); + break; + default: + throw new AssertError("Invalid newarray operand"); + } + } catch (NegativeArraySizeException ex) { + throw new InvocationTargetException(ex); + } break; - case 11: - stack[stacktop++].setObject(new long[length]); + } + case opc_anewarray: { + int length = stack[--stacktop].intValue(); + try { + stack[stacktop++].setObject + (env.newArray((String) instr.objData, + new int[] { length })); + } catch (NegativeArraySizeException ex) { + throw new InvocationTargetException(ex); + } break; - default: - throw new ClassFormatException("Invalid newarray operand"); } - break; - } - case opc_anewarray: { - int length = stack[--stacktop].intValue(); - Class clazz; - try { - clazz = Class.forName((String) instr.objData); - } catch (ClassNotFoundException ex) { - throw new InterpreterException - ("Class "+ex.getMessage()+" not found"); + case opc_arraylength: { + Object array = stack[--stacktop].objectValue(); + stack[stacktop++].setInt(Array.getLength(array)); + break; } - stack[stacktop++].setObject(Array.newInstance(clazz, length)); - break; - } - case opc_arraylength: { - Object array = stack[--stacktop].objectValue(); - stack[stacktop++].setInt(Array.getLength(array)); - break; - } - case opc_athrow: - /*XXX Throw and catch ?? */ - throw new InterpreterException("Throw not implemented"); - case opc_checkcast: { - Class clazz; - try { - clazz = Class.forName((String) instr.objData); - } catch (ClassNotFoundException ex) { - throw new InterpreterException - ("Class "+ex.getMessage()+" not found"); + case opc_athrow: { + Throwable exc = + (Throwable) stack[--stacktop].objectValue(); + throw new InvocationTargetException + (exc == null ? new NullPointerException() : exc); } - Object obj = stack[stacktop-1].objectValue(); - if (obj != null && !clazz.isInstance(obj)) { - /*XXX*/ - throw new InterpreterException - ("Throw ClassCastException not implemented"); + case opc_checkcast: { + Object obj = stack[stacktop-1].objectValue(); + if (obj != null + && !env.instanceOf(obj, (String) instr.objData)) + throw new InvocationTargetException + (new ClassCastException(obj.getClass().getName())); + break; } - break; - } - case opc_instanceof: { - Class clazz; - try { - clazz = Class.forName((String) instr.objData); - } catch (ClassNotFoundException ex) { - throw new InterpreterException - ("Class "+ex.getMessage()+" not found"); + case opc_instanceof: { + Object obj = stack[--stacktop].objectValue(); + stack[stacktop++].setInt + (env.instanceOf(obj, (String) instr.objData) ? 1 : 0); + break; } - Object obj = stack[--stacktop].objectValue(); - if (obj != null && !clazz.isInstance(obj)) { - /*XXX*/ - throw new InterpreterException - ("Throw ClassCastException not implemented"); + case opc_monitorenter: + env.enterMonitor(stack[--stacktop].objectValue()); + break; + case opc_monitorexit: + env.exitMonitor(stack[--stacktop].objectValue()); + break; + case opc_multianewarray: { + int dimension = instr.intData; + int[] dims = new int[dimension]; + for (int i=dimension - 1; i >= 0; i--) + dims[i-1] = stack[--stacktop].intValue(); + try { + stack[stacktop++].setObject + (env.newArray((String) instr.objData, dims)); + } catch (NegativeArraySizeException ex) { + throw new InvocationTargetException(ex); + } + break; } - break; - } - case opc_monitorenter: - case opc_monitorexit: - throw new InterpreterException - ("MonitorEnter/Exit not implemented"); - case opc_multianewarray: { - Class clazz; - try { - clazz = Class.forName((String) instr.objData); - } catch (ClassNotFoundException ex) { - throw new InterpreterException - ("Class "+ex.getMessage()+" not found"); + default: + throw new AssertError("Invalid opcode "+opcode); } - int dimension = instr.intData; - int[] dims = new int[dimension]; - for (int i=dimension - 1; i >= 0; i--) - dims[i-1] = stack[--stacktop].intValue(); - stack[stacktop++].setObject(Array.newInstance(clazz, dims)); - break; - } - default: - throw new ClassFormatException("Invalid opcode "+opcode); + } catch (InvocationTargetException ex) { + Handler[] handlers = code.getExceptionHandlers(); + Throwable obj = ex.getTargetException(); + for (int i=0; i< handlers.length; i++) { + if (handlers[i].start.addr <= pc.addr + && handlers[i].end.addr >= pc.addr + && (handlers[i].type == null + || env.instanceOf(obj, handlers[i].type))) { + stacktop = 0; + stack[stacktop++].setObject(obj); + pc = handlers[i].catcher; + continue big_loop; + } + } + throw ex; } } - } catch(RuntimeException ex) { - ex.printStackTrace(); - throw new InterpreterException("Caught RuntimeException: " - + ex.toString()); - } } }