fix in checkcast

Use Reference
simplification of opcodes


git-svn-id: https://svn.code.sf.net/p/jode/code/trunk@496 379699f6-c40d-0410-875b-85095c16579e
stable
jochen 26 years ago
parent 7cbfee8e50
commit 4b6fdba442
  1. 203
      jode/jode/jvm/Interpreter.java

@ -1,26 +1,26 @@
/* /* Interpreter Copyright (C) 1999 Jochen Hoenicke.
* Opcodes (c) 1998 Jochen Hoenicke
* *
* You may distribute under the terms of the GNU General Public License. * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
* *
* IN NO EVENT SHALL JOCHEN HOENICKE BE LIABLE TO ANY PARTY FOR DIRECT, * This program is distributed in the hope that it will be useful,
* INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF * but WITHOUT ANY WARRANTY; without even the implied warranty of
* THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF JOCHEN HOENICKE * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * GNU General Public License for more details.
* *
* JOCHEN HOENICKE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT * You should have received a copy of the GNU General Public License
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * along with this program; see the file COPYING. If not, write to
* PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* BASIS, AND JOCHEN HOENICKE HAS NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
* *
* $Id$ * $Id$
*/ */
package jode.jvm; package jode.jvm;
import jode.*;
import jode.bytecode.*; import jode.bytecode.*;
import jode.decompiler.ClassAnalyzer; import jode.decompiler.ClassAnalyzer;
import jode.MethodType;
import jode.Type;
import java.lang.reflect.*; import java.lang.reflect.*;
/** /**
@ -32,84 +32,46 @@ import java.lang.reflect.*;
*/ */
public class Interpreter implements Opcodes { public class Interpreter implements Opcodes {
static int checkType(String typesig, int pos, Class type) { static boolean checkType(Type type1, Class type2) {
switch (typesig.charAt(pos++)) { if (type1 == Type.tBoolean) {
case 'Z': return type2 == Boolean.TYPE;
if (type != Boolean.TYPE) } else if (type1 == Type.tByte) {
return -1; return type2 == Byte.TYPE;
break; } else if (type1 == Type.tChar) {
case 'B': return type2 == Character.TYPE;
if (type != Byte.TYPE) } else if (type1 == Type.tShort) {
return -1; return type2 == Short.TYPE;
break; } else if (type1 == Type.tInt) {
case 'C': return type2 == Integer.TYPE;
if (type != Character.TYPE) } else if (type1 == Type.tLong) {
return -1; return type2 == Long.TYPE;
break; } else if (type1 == Type.tFloat) {
case 'S': return type2 == Float.TYPE;
if (type != Short.TYPE) } else if (type1 == Type.tDouble) {
return -1; return type2 == Double.TYPE;
break; } else if (type1 == Type.tVoid) {
case 'I': return type2 == Void.TYPE;
if (type != Integer.TYPE) } else if (type1 instanceof ArrayType) {
return -1; if (!type2.isArray())
break; return false;
case 'J': return checkType(((ArrayType)type1).getElementType(),
if (type != Long.TYPE) type2.getComponentType());
return -1; } else if (type1 instanceof ClassInterfacesType) {
break; return type1.equals(Type.tClass(type2.getName()));
case 'F': } else
if (type != Float.TYPE) return false;
return -1;
break;
case 'D':
if (type != Double.TYPE)
return -1;
break;
case 'V':
if (type != Void.TYPE)
return -1;
break;
case '[':
if (!type.isArray())
return -1;
pos = checkType(typesig, pos, type.getComponentType());
break;
case 'L': {
int index = typesig.indexOf(';', pos);
if (index == -1)
return -1;
if (!type.getName().replace('.','/')
.equals(typesig.substring(pos, index)))
return -1;
pos = index+1;
break;
}
default:
return -1;
}
return pos;
} }
static boolean checkMethod(String typesig, static boolean checkMethod(MethodType methodType,
Class[] paramTypes, Class retType) { Class[] paramTypes, Class retType) {
if (typesig.charAt(0) != '(') Type[] params = methodType.getParameterTypes();
return false; if (params.length != paramTypes.length)
int pos = 1;
int i = 0;
while (typesig.charAt(pos) != ')') {
if (i >= paramTypes.length)
return false; return false;
pos = checkType(typesig, pos, paramTypes[i++]); for (int i=0; i < params.length; i++) {
if (pos == -1) { if (!checkType(params[i], paramTypes[i]))
return false; return false;
} }
} return checkType(methodType.getReturnType(), retType);
if (i != paramTypes.length)
return false;
pos++;
pos = checkType(typesig, pos, retType);
return pos == typesig.length();
} }
public static Object interpretMethod public static Object interpretMethod
@ -139,17 +101,7 @@ public class Interpreter implements Opcodes {
switch (opcode) { switch (opcode) {
case opc_nop: case opc_nop:
break; break;
case opc_aconst_null:
case opc_iconst_m1:
case opc_iconst_0: case opc_iconst_1: case opc_iconst_2:
case opc_iconst_3: case opc_iconst_4: case opc_iconst_5:
case opc_lconst_0: case opc_lconst_1:
case opc_fconst_0: case opc_fconst_1: case opc_fconst_2:
case opc_dconst_0: case opc_dconst_1:
case opc_bipush:
case opc_sipush:
case opc_ldc: case opc_ldc:
case opc_ldc_w:
case opc_ldc2_w: { case opc_ldc2_w: {
stack[stacktop++].setObject(instr.objData); stack[stacktop++].setObject(instr.objData);
break; break;
@ -600,12 +552,11 @@ public class Interpreter implements Opcodes {
case opc_invokespecial: case opc_invokespecial:
case opc_invokestatic : case opc_invokestatic :
case opc_invokeinterface: { case opc_invokeinterface: {
String[] ref = (String[]) instr.objData; Reference ref = (Reference) instr.objData;
if (ref[0].equals(ca.getClazz().getName().replace('.','/'))) { if (ref.getClazz().equals(ca.getClazz().getName())) {
boolean isStatic = opcode == opc_invokestatic; MethodType mt = (MethodType) Type.tType(ref.getType());
MethodType mt = new MethodType(isStatic, ref[2]); BytecodeInfo info = ca.getMethod(ref.getName(), mt)
BytecodeInfo info = ca.getMethod(ref[1], mt)
.getCode().getBytecodeInfo(); .getCode().getBytecodeInfo();
Value[] newLocals = new Value[info.getMaxLocals()]; Value[] newLocals = new Value[info.getMaxLocals()];
for (int i=0; i< newLocals.length; i++) for (int i=0; i< newLocals.length; i++)
@ -613,8 +564,14 @@ public class Interpreter implements Opcodes {
Value[] newStack = new Value[info.getMaxStack()]; Value[] newStack = new Value[info.getMaxStack()];
for (int i=0; i< newStack.length; i++) for (int i=0; i< newStack.length; i++)
newStack[i] = new Value(); newStack[i] = new Value();
for (int i=mt.getParameterTypes().length - 1; i >= 0; i--) int param = mt.getParameterTypes().length;
newLocals[i].setValue(stack[--stacktop]); 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, Object result = interpretMethod(ca, info,
newLocals, newStack); newLocals, newStack);
if (mt.getReturnType() != Type.tVoid) if (mt.getReturnType() != Type.tVoid)
@ -622,41 +579,43 @@ public class Interpreter implements Opcodes {
} else { } else {
Class clazz; Class clazz;
try { try {
clazz = Class.forName(ref[0].replace('/','.')); clazz = Class.forName(ref.getClazz());
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
throw new InterpreterException throw new InterpreterException
("Class "+ref[0]+" not found"); ("Class "+ref.getClazz()+" not found");
} }
try { try {
if (ref[1].equals("<init>")) { if (ref.getName().equals("<init>")) {
Constructor[] cs = clazz.getConstructors(); Constructor[] cs = clazz.getConstructors();
Constructor c = null; Constructor c = null;
for (int i=0; i< cs.length; i++) { for (int i=0; i< cs.length; i++) {
if (checkMethod(ref[2], cs[i].getParameterTypes(), if (checkMethod((MethodType)
Type.tType(ref.getType()),
cs[i].getParameterTypes(),
Void.TYPE)) { Void.TYPE)) {
c = cs[i]; c = cs[i];
break; break;
} }
} }
if (c == null) if (c == null)
throw new InterpreterException("Constructor " throw new InterpreterException
+ref[0]+"." ("Constructor " + ref + " not found.");
+ref[1]+" not found.");
Object[] args Object[] args
= new Object[c.getParameterTypes().length]; = new Object[c.getParameterTypes().length];
for (int i=args.length - 1; i >= 0; i--) for (int i=args.length - 1; i >= 0; i--)
args[i] = stack[--stacktop].objectValue(); args[i] = stack[--stacktop].objectValue();
NewObject newObj = stack[--stacktop].getNewObject(); NewObject newObj = stack[--stacktop].getNewObject();
if (!newObj.getType().equals(ref[0])) if (!newObj.getType().equals(ref.getClazz()))
throw new InterpreterException("constructor not called" throw new InterpreterException
+" on new instance"); ("constructor called on wrong type");
newObj.setObject(c.newInstance(args)); newObj.setObject(c.newInstance(args));
} else { } else {
Method[] ms = clazz.getMethods(); Method[] ms = clazz.getMethods();
Method m = null; Method m = null;
for (int i=0; i< ms.length; i++) { for (int i=0; i< ms.length; i++) {
if (ms[i].getName().equals(ref[1])) { if (ms[i].getName().equals(ref.getName())) {
if (checkMethod(ref[2], if (checkMethod((MethodType)
Type.tType(ref.getType()),
ms[i].getParameterTypes(), ms[i].getParameterTypes(),
ms[i].getReturnType())) { ms[i].getReturnType())) {
m = ms[i]; m = ms[i];
@ -665,8 +624,8 @@ public class Interpreter implements Opcodes {
} }
} }
if (m == null) if (m == null)
throw new InterpreterException("Method "+ref[0]+"." throw new InterpreterException
+ref[1]+" not found."); ("Method " + ref + " not found.");
Object obj = null; Object obj = null;
Object[] args Object[] args
= new Object[m.getParameterTypes().length]; = new Object[m.getParameterTypes().length];
@ -681,13 +640,13 @@ public class Interpreter implements Opcodes {
} }
} catch (IllegalAccessException ex) { } catch (IllegalAccessException ex) {
throw new InterpreterException throw new InterpreterException
("Method "+ref[0]+"."+ref[1]+" not accessible"); ("Method " + ref + " not accessible");
} catch (InstantiationException ex) { } catch (InstantiationException ex) {
throw new InterpreterException throw new InterpreterException
("InstantiationException in "+ref[0]+"."+ref[1]+"."); ("InstantiationException in " + ref + ".");
} catch (InvocationTargetException ex) { } catch (InvocationTargetException ex) {
throw new InterpreterException throw new InterpreterException
("Method "+ref[0]+"."+ref[1]+" throwed an exception"); ("Method " + ref + " throwed an exception");
/*XXX exception handler?*/ /*XXX exception handler?*/
} }
} }
@ -758,7 +717,7 @@ public class Interpreter implements Opcodes {
throw new InterpreterException throw new InterpreterException
("Class "+ex.getMessage()+" not found"); ("Class "+ex.getMessage()+" not found");
} }
Object obj = stack[--stacktop].objectValue(); Object obj = stack[stacktop-1].objectValue();
if (obj != null && !clazz.isInstance(obj)) { if (obj != null && !clazz.isInstance(obj)) {
/*XXX*/ /*XXX*/
throw new InterpreterException throw new InterpreterException
@ -796,7 +755,7 @@ public class Interpreter implements Opcodes {
} }
int dimension = instr.intData; int dimension = instr.intData;
int[] dims = new int[dimension]; int[] dims = new int[dimension];
for (int i=dimension-1; i >= 0; i--) for (int i=dimension - 1; i >= 0; i--)
dims[i-1] = stack[--stacktop].intValue(); dims[i-1] = stack[--stacktop].intValue();
stack[stacktop++].setObject(Array.newInstance(clazz, dims)); stack[stacktop++].setObject(Array.newInstance(clazz, dims));
break; break;

Loading…
Cancel
Save