diff --git a/classpath/avian/ClassAddendum.java b/classpath/avian/ClassAddendum.java index 6958a7a3ca..c20079df6b 100644 --- a/classpath/avian/ClassAddendum.java +++ b/classpath/avian/ClassAddendum.java @@ -11,5 +11,6 @@ package avian; public class ClassAddendum extends Addendum { + public volatile Class class_; public Object[] signers; } diff --git a/classpath/avian/SystemClassLoader.java b/classpath/avian/SystemClassLoader.java index 2257a9b66e..4ad1e3130a 100644 --- a/classpath/avian/SystemClassLoader.java +++ b/classpath/avian/SystemClassLoader.java @@ -13,6 +13,7 @@ package avian; import static avian.Stream.read1; import static avian.Stream.read2; +import java.lang.reflect.Modifier; import java.lang.reflect.Method; import java.lang.reflect.Field; import java.net.URL; @@ -24,16 +25,26 @@ import java.io.IOException; public class SystemClassLoader extends ClassLoader { private static final int LinkFlag = 1 << 8; - public static native Class defineClass + public static native VMClass defineVMClass (ClassLoader loader, byte[] b, int offset, int length); - protected native Class findClass(String name) throws ClassNotFoundException; + private static native VMClass findVMClass(String name) + throws ClassNotFoundException; - protected native Class reallyFindLoadedClass(String name); + protected Class findClass(String name) throws ClassNotFoundException { + return getClass(findVMClass(name)); + } - private native boolean resourceExists(String name); + private static native VMClass findLoadedVMClass(String name); - private static native Class resolveClass(ClassLoader loader, byte[] spec) + protected Class reallyFindLoadedClass(String name){ + VMClass c = findLoadedVMClass(name); + return c == null ? null : getClass(c); + } + + private static native boolean resourceExists(String name); + + private static native VMClass resolveVMClass(ClassLoader loader, byte[] spec) throws ClassNotFoundException; protected URL findResource(String name) { @@ -45,14 +56,14 @@ public class SystemClassLoader extends ClassLoader { return null; } - private static Class loadClass(ClassLoader loader, - byte[] nameBytes, int offset, int length) + private static VMClass loadVMClass(ClassLoader loader, + byte[] nameBytes, int offset, int length) { byte[] spec = new byte[length + 1]; System.arraycopy(nameBytes, offset, spec, 0, length); try { - Class c = resolveClass(loader, spec); + VMClass c = resolveVMClass(loader, spec); if (c == null) { throw new NoClassDefFoundError(); } @@ -110,14 +121,14 @@ public class SystemClassLoader extends ClassLoader { byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1); return Enum.valueOf - (loadClass(loader, typeName, 1, typeName.length - 3), + (getClass(loadVMClass(loader, typeName, 1, typeName.length - 3)), new String(name, 0, name.length - 1, false)); } case 'c':{ byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1); - return loadClass(loader, name, 1, name.length - 3); + return getClass(loadVMClass(loader, name, 1, name.length - 3)); } case '@': @@ -142,7 +153,8 @@ public class SystemClassLoader extends ClassLoader { { byte[] typeName = (byte[]) Singleton.getObject(pool, read2(in) - 1); Object[] annotation = new Object[(read2(in) + 1) * 2]; - annotation[1] = loadClass(loader, typeName, 1, typeName.length - 3); + annotation[1] = getClass + (loadVMClass(loader, typeName, 1, typeName.length - 3)); for (int i = 2; i < annotation.length; i += 2) { byte[] name = (byte[]) Singleton.getObject(pool, read2(in) - 1); @@ -214,7 +226,7 @@ public class SystemClassLoader extends ClassLoader { return start + 1; } - loadClass(loader, spec, start, end - start); + loadVMClass(loader, spec, start, end - start); return result; } @@ -223,7 +235,35 @@ public class SystemClassLoader extends ClassLoader { private static native void releaseClassLock(); - public static void link(Class c, ClassLoader loader) { + public static Class getClass(VMClass vmClass) { + if (vmClass.addendum == null) { + SystemClassLoader.acquireClassLock(); + try { + if (vmClass.addendum == null) { + vmClass.addendum = new ClassAddendum(); + } + } finally { + SystemClassLoader.releaseClassLock(); + } + } + + if (vmClass.addendum.class_ == null) { + SystemClassLoader.acquireClassLock(); + try { + if (vmClass.addendum.class_ == null) { + vmClass.addendum.class_ = new Class(vmClass); + } + } finally { + SystemClassLoader.releaseClassLock(); + } + } + + return vmClass.addendum.class_; + } + + public static native VMClass getVMClass(Object o); + + public static void link(VMClass c, ClassLoader loader) { acquireClassLock(); try { if ((c.vmFlags & LinkFlag) == 0) { @@ -234,15 +274,15 @@ public class SystemClassLoader extends ClassLoader { parseAnnotationTable(loader, c.addendum); if (c.interfaceTable != null) { - int stride = (c.isInterface() ? 1 : 2); + int stride = ((c.flags & Modifier.INTERFACE) != 0 ? 1 : 2); for (int i = 0; i < c.interfaceTable.length; i += stride) { - link((Class) c.interfaceTable[i], loader); + link((VMClass) c.interfaceTable[i], loader); } } if (c.methodTable != null) { for (int i = 0; i < c.methodTable.length; ++i) { - Method m = c.methodTable[i]; + VMMethod m = c.methodTable[i]; for (int j = 1; j < m.spec.length;) { j = resolveSpec(loader, m.spec, j); @@ -254,7 +294,7 @@ public class SystemClassLoader extends ClassLoader { if (c.fieldTable != null) { for (int i = 0; i < c.fieldTable.length; ++i) { - Field f = c.fieldTable[i]; + VMField f = c.fieldTable[i]; resolveSpec(loader, f.spec, 0); @@ -269,7 +309,7 @@ public class SystemClassLoader extends ClassLoader { } } - public static void link(Class c) { - link(c, c.getClassLoader()); + public static void link(VMClass c) { + link(c, c.loader); } } diff --git a/classpath/avian/VMClass.java b/classpath/avian/VMClass.java new file mode 100644 index 0000000000..da9a64f832 --- /dev/null +++ b/classpath/avian/VMClass.java @@ -0,0 +1,30 @@ +/* Copyright (c) 2008-2010, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class VMClass { + public short flags; + public short vmFlags; + public short fixedSize; + public byte arrayElementSize; + public byte arrayDimensions; + public int[] objectMask; + public byte[] name; + public byte[] sourceFile; + public VMClass super_; + public Object[] interfaceTable; + public VMMethod[] virtualTable; + public VMField[] fieldTable; + public VMMethod[] methodTable; + public volatile avian.ClassAddendum addendum; + public Object staticTable; + public ClassLoader loader; +} diff --git a/classpath/avian/VMField.java b/classpath/avian/VMField.java new file mode 100644 index 0000000000..96c2959f73 --- /dev/null +++ b/classpath/avian/VMField.java @@ -0,0 +1,22 @@ +/* Copyright (c) 2008-2010, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class VMField { + public byte vmFlags; + public byte code; + public short flags; + public short offset; + public byte[] name; + public byte[] spec; + public avian.Addendum addendum; + public VMClass class_; +} diff --git a/classpath/avian/VMMethod.java b/classpath/avian/VMMethod.java new file mode 100644 index 0000000000..374b424d84 --- /dev/null +++ b/classpath/avian/VMMethod.java @@ -0,0 +1,26 @@ +/* Copyright (c) 2008-2010, Avian Contributors + + Permission to use, copy, modify, and/or distribute this software + for any purpose with or without fee is hereby granted, provided + that the above copyright notice and this permission notice appear + in all copies. + + There is NO WARRANTY for this software. See license.txt for + details. */ + +package avian; + +public class VMMethod { + public byte vmFlags; + public byte returnCode; + public byte parameterCount; + public byte parameterFootprint; + public short flags; + public short offset; + public int nativeID; + public byte[] name; + public byte[] spec; + public avian.Addendum addendum; + public VMClass class_; + public Object code; +} diff --git a/classpath/java/lang/Class.java b/classpath/java/lang/Class.java index de7d3b0fc8..4b053d89ca 100644 --- a/classpath/java/lang/Class.java +++ b/classpath/java/lang/Class.java @@ -10,7 +10,10 @@ package java.lang; +import avian.VMClass; +import avian.ClassAddendum; import avian.AnnotationInvocationHandler; +import avian.SystemClassLoader; import java.lang.reflect.Constructor; import java.lang.reflect.Method; @@ -38,24 +41,13 @@ public final class Class { private static final int PrimitiveFlag = 1 << 5; - private short flags; - public short vmFlags; - private short fixedSize; - private byte arrayElementSize; - private byte arrayDimensions; - private int[] objectMask; - private byte[] name; - private byte[] sourceFile; - public Class super_; - public Object[] interfaceTable; - public Method[] virtualTable; - public Field[] fieldTable; - public Method[] methodTable; - public avian.ClassAddendum addendum; - private Object staticTable; - private ClassLoader loader; + public final VMClass vmClass; - private Class() { } + public Class(VMClass vmClass) { + this.vmClass = vmClass; + } + + public static native VMClass vmClass(Object o); public String toString() { return getName(); @@ -73,26 +65,30 @@ public final class Class } public String getName() { - if (name == null) { - if ((vmFlags & PrimitiveFlag) != 0) { - if (this == primitiveClass('V')) { - name = "void\0".getBytes(); - } else if (this == primitiveClass('Z')) { - name = "boolean\0".getBytes(); - } else if (this == primitiveClass('B')) { - name = "byte\0".getBytes(); - } else if (this == primitiveClass('C')) { - name = "char\0".getBytes(); - } else if (this == primitiveClass('S')) { - name = "short\0".getBytes(); - } else if (this == primitiveClass('I')) { - name = "int\0".getBytes(); - } else if (this == primitiveClass('F')) { - name = "float\0".getBytes(); - } else if (this == primitiveClass('J')) { - name = "long\0".getBytes(); - } else if (this == primitiveClass('D')) { - name = "double\0".getBytes(); + return getName(vmClass); + } + + public static String getName(VMClass c) { + if (c.name == null) { + if ((c.vmFlags & PrimitiveFlag) != 0) { + if (c == primitiveClass('V')) { + c.name = "void\0".getBytes(); + } else if (c == primitiveClass('Z')) { + c.name = "boolean\0".getBytes(); + } else if (c == primitiveClass('B')) { + c.name = "byte\0".getBytes(); + } else if (c == primitiveClass('C')) { + c.name = "char\0".getBytes(); + } else if (c == primitiveClass('S')) { + c.name = "short\0".getBytes(); + } else if (c == primitiveClass('I')) { + c.name = "int\0".getBytes(); + } else if (c == primitiveClass('F')) { + c.name = "float\0".getBytes(); + } else if (c == primitiveClass('J')) { + c.name = "long\0".getBytes(); + } else if (c == primitiveClass('D')) { + c.name = "double\0".getBytes(); } else { throw new AssertionError(); } @@ -102,11 +98,12 @@ public final class Class } return new String - (replace('/', '.', name, 0, name.length - 1), 0, name.length - 1, false); + (replace('/', '.', c.name, 0, c.name.length - 1), 0, c.name.length - 1, + false); } public String getCanonicalName() { - if ((vmFlags & PrimitiveFlag) != 0) { + if ((vmClass.vmFlags & PrimitiveFlag) != 0) { return getName(); } else if (isArray()) { return getComponentType().getCanonicalName() + "[]"; @@ -116,7 +113,7 @@ public final class Class } public String getSimpleName() { - if ((vmFlags & PrimitiveFlag) != 0) { + if ((vmClass.vmFlags & PrimitiveFlag) != 0) { return getName(); } else if (isArray()) { return getComponentType().getSimpleName() + "[]"; @@ -131,10 +128,6 @@ public final class Class } } - public Object staticTable() { - return staticTable; - } - public T newInstance() throws IllegalAccessException, InstantiationException { @@ -148,8 +141,7 @@ public final class Class } public static Class forName(String name) throws ClassNotFoundException { - return forName - (name, true, Method.getCaller().getDeclaringClass().getClassLoader()); + return forName(name, true, Method.getCaller().class_.loader); } public static Class forName(String name, boolean initialize, @@ -157,19 +149,19 @@ public final class Class throws ClassNotFoundException { if (loader == null) { - loader = Class.class.loader; + loader = Class.class.vmClass.loader; } Class c = loader.loadClass(name); - avian.SystemClassLoader.link(c, loader); + SystemClassLoader.link(c.vmClass, loader); if (initialize) { - c.initialize(); + initialize(c.vmClass); } return c; } - private static native Class primitiveClass(char name); + private static native VMClass primitiveClass(char name); - private native void initialize(); + private static native void initialize(VMClass vmClass); public static Class forCanonicalName(String name) { return forCanonicalName(null, name); @@ -183,7 +175,7 @@ public final class Class return forName(name.substring(1, name.length() - 1), true, loader); } else { if (name.length() == 1) { - return primitiveClass(name.charAt(0)); + return SystemClassLoader.getClass(primitiveClass(name.charAt(0))); } else { throw new ClassNotFoundException(name); } @@ -197,39 +189,43 @@ public final class Class if (isArray()) { String n = getName(); if ("[Z".equals(n)) { - return primitiveClass('Z'); + return SystemClassLoader.getClass(primitiveClass('Z')); } else if ("[B".equals(n)) { - return primitiveClass('B'); + return SystemClassLoader.getClass(primitiveClass('B')); } else if ("[S".equals(n)) { - return primitiveClass('S'); + return SystemClassLoader.getClass(primitiveClass('S')); } else if ("[C".equals(n)) { - return primitiveClass('C'); + return SystemClassLoader.getClass(primitiveClass('C')); } else if ("[I".equals(n)) { - return primitiveClass('I'); + return SystemClassLoader.getClass(primitiveClass('I')); } else if ("[F".equals(n)) { - return primitiveClass('F'); + return SystemClassLoader.getClass(primitiveClass('F')); } else if ("[J".equals(n)) { - return primitiveClass('J'); + return SystemClassLoader.getClass(primitiveClass('J')); } else if ("[D".equals(n)) { - return primitiveClass('D'); + return SystemClassLoader.getClass(primitiveClass('D')); } - if (staticTable == null) throw new AssertionError(name); - return (Class) staticTable; + if (vmClass.staticTable == null) throw new AssertionError(); + return SystemClassLoader.getClass((VMClass) vmClass.staticTable); } else { return null; } } - public native boolean isAssignableFrom(Class c); + public static native boolean isAssignableFrom(VMClass a, VMClass b); - private Field findField(String name) { - if (fieldTable != null) { - avian.SystemClassLoader.link(this); + public boolean isAssignableFrom(Class c) { + return isAssignableFrom(vmClass, c.vmClass); + } - for (int i = 0; i < fieldTable.length; ++i) { - if (fieldTable[i].getName().equals(name)) { - return fieldTable[i]; + private static Field findField(VMClass vmClass, String name) { + if (vmClass.fieldTable != null) { + SystemClassLoader.link(vmClass); + + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + if (Field.getName(vmClass.fieldTable[i]).equals(name)) { + return new Field(vmClass.fieldTable[i]); } } } @@ -237,7 +233,7 @@ public final class Class } public Field getDeclaredField(String name) throws NoSuchFieldException { - Field f = findField(name); + Field f = findField(vmClass, name); if (f == null) { throw new NoSuchFieldException(name); } else { @@ -246,8 +242,8 @@ public final class Class } public Field getField(String name) throws NoSuchFieldException { - for (Class c = this; c != null; c = c.super_) { - Field f = c.findField(name); + for (VMClass c = vmClass; c != null; c = c.super_) { + Field f = findField(c, name); if (f != null) { return f; } @@ -268,19 +264,22 @@ public final class Class } } - private Method findMethod(String name, Class[] parameterTypes) { - if (methodTable != null) { - avian.SystemClassLoader.link(this); + private static Method findMethod(VMClass vmClass, String name, + Class[] parameterTypes) + { + if (vmClass.methodTable != null) { + SystemClassLoader.link(vmClass); if (parameterTypes == null) { parameterTypes = new Class[0]; } - for (int i = 0; i < methodTable.length; ++i) { - if (methodTable[i].getName().equals(name) - && match(parameterTypes, methodTable[i].getParameterTypes())) + for (int i = 0; i < vmClass.methodTable.length; ++i) { + if (Method.getName(vmClass.methodTable[i]).equals(name) + && match(parameterTypes, + Method.getParameterTypes(vmClass.methodTable[i]))) { - return methodTable[i]; + return new Method(vmClass.methodTable[i]); } } } @@ -293,7 +292,7 @@ public final class Class if (name.startsWith("<")) { throw new NoSuchMethodException(name); } - Method m = findMethod(name, parameterTypes); + Method m = findMethod(vmClass, name, parameterTypes); if (m == null) { throw new NoSuchMethodException(name); } else { @@ -307,8 +306,8 @@ public final class Class if (name.startsWith("<")) { throw new NoSuchMethodException(name); } - for (Class c = this; c != null; c = c.super_) { - Method m = c.findMethod(name, parameterTypes); + for (VMClass c = vmClass; c != null; c = c.super_) { + Method m = findMethod(c, name, parameterTypes); if (m != null) { return m; } @@ -319,7 +318,7 @@ public final class Class public Constructor getConstructor(Class ... parameterTypes) throws NoSuchMethodException { - Method m = findMethod("", parameterTypes); + Method m = findMethod(vmClass, "", parameterTypes); if (m == null) { throw new NoSuchMethodException(); } else { @@ -348,11 +347,12 @@ public final class Class private int countConstructors(boolean publicOnly) { int count = 0; - if (methodTable != null) { - for (int i = 0; i < methodTable.length; ++i) { + if (vmClass.methodTable != null) { + for (int i = 0; i < vmClass.methodTable.length; ++i) { if (((! publicOnly) - || ((methodTable[i].getModifiers() & Modifier.PUBLIC)) != 0) - && methodTable[i].getName().equals("")) + || ((vmClass.methodTable[i].flags & Modifier.PUBLIC)) + != 0) + && Method.getName(vmClass.methodTable[i]).equals("")) { ++ count; } @@ -363,13 +363,13 @@ public final class Class public Constructor[] getDeclaredConstructors() { Constructor[] array = new Constructor[countConstructors(false)]; - if (methodTable != null) { - avian.SystemClassLoader.link(this); + if (vmClass.methodTable != null) { + SystemClassLoader.link(vmClass); int index = 0; - for (int i = 0; i < methodTable.length; ++i) { - if (methodTable[i].getName().equals("")) { - array[index++] = new Constructor(methodTable[i]); + for (int i = 0; i < vmClass.methodTable.length; ++i) { + if (Method.getName(vmClass.methodTable[i]).equals("")) { + array[index++] = new Constructor(new Method(vmClass.methodTable[i])); } } } @@ -379,15 +379,15 @@ public final class Class public Constructor[] getConstructors() { Constructor[] array = new Constructor[countConstructors(true)]; - if (methodTable != null) { - avian.SystemClassLoader.link(this); + if (vmClass.methodTable != null) { + SystemClassLoader.link(vmClass); int index = 0; - for (int i = 0; i < methodTable.length; ++i) { - if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0) - && methodTable[i].getName().equals("")) + for (int i = 0; i < vmClass.methodTable.length; ++i) { + if (((vmClass.methodTable[i].flags & Modifier.PUBLIC) != 0) + && Method.getName(vmClass.methodTable[i]).equals("")) { - array[index++] = new Constructor(methodTable[i]); + array[index++] = new Constructor(new Method(vmClass.methodTable[i])); } } } @@ -396,9 +396,11 @@ public final class Class } public Field[] getDeclaredFields() { - if (fieldTable != null) { - Field[] array = new Field[fieldTable.length]; - System.arraycopy(fieldTable, 0, array, 0, fieldTable.length); + if (vmClass.fieldTable != null) { + Field[] array = new Field[vmClass.fieldTable.length]; + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + array[i] = new Field(vmClass.fieldTable[i]); + } return array; } else { return new Field[0]; @@ -407,9 +409,9 @@ public final class Class private int countPublicFields() { int count = 0; - if (fieldTable != null) { - for (int i = 0; i < fieldTable.length; ++i) { - if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) { + if (vmClass.fieldTable != null) { + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + if (((vmClass.fieldTable[i].flags & Modifier.PUBLIC)) != 0) { ++ count; } } @@ -419,13 +421,13 @@ public final class Class public Field[] getFields() { Field[] array = new Field[countPublicFields()]; - if (fieldTable != null) { - avian.SystemClassLoader.link(this); + if (vmClass.fieldTable != null) { + SystemClassLoader.link(vmClass); int ai = 0; - for (int i = 0; i < fieldTable.length; ++i) { - if (((fieldTable[i].getModifiers() & Modifier.PUBLIC)) != 0) { - array[ai++] = fieldTable[i]; + for (int i = 0; i < vmClass.fieldTable.length; ++i) { + if (((vmClass.fieldTable[i].flags & Modifier.PUBLIC)) != 0) { + array[ai++] = new Field(vmClass.fieldTable[i]); } } } @@ -434,11 +436,12 @@ public final class Class private int countMethods(boolean publicOnly) { int count = 0; - if (methodTable != null) { - for (int i = 0; i < methodTable.length; ++i) { + if (vmClass.methodTable != null) { + for (int i = 0; i < vmClass.methodTable.length; ++i) { if (((! publicOnly) - || ((methodTable[i].getModifiers() & Modifier.PUBLIC)) != 0) - && (! methodTable[i].getName().startsWith("<"))) + || ((vmClass.methodTable[i].flags & Modifier.PUBLIC)) + != 0) + && (! Method.getName(vmClass.methodTable[i]).startsWith("<"))) { ++ count; } @@ -449,13 +452,13 @@ public final class Class public Method[] getDeclaredMethods() { Method[] array = new Method[countMethods(false)]; - if (methodTable != null) { - avian.SystemClassLoader.link(this); + if (vmClass.methodTable != null) { + SystemClassLoader.link(vmClass); int ai = 0; - for (int i = 0; i < methodTable.length; ++i) { - if (! methodTable[i].getName().startsWith("<")) { - array[ai++] = methodTable[i]; + for (int i = 0; i < vmClass.methodTable.length; ++i) { + if (! Method.getName(vmClass.methodTable[i]).startsWith("<")) { + array[ai++] = new Method(vmClass.methodTable[i]); } } } @@ -465,15 +468,15 @@ public final class Class public Method[] getMethods() { Method[] array = new Method[countMethods(true)]; - if (methodTable != null) { - avian.SystemClassLoader.link(this); + if (vmClass.methodTable != null) { + SystemClassLoader.link(vmClass); int index = 0; - for (int i = 0; i < methodTable.length; ++i) { - if (((methodTable[i].getModifiers() & Modifier.PUBLIC) != 0) - && (! methodTable[i].getName().startsWith("<"))) + for (int i = 0; i < vmClass.methodTable.length; ++i) { + if (((vmClass.methodTable[i].flags & Modifier.PUBLIC) != 0) + && (! Method.getName(vmClass.methodTable[i]).startsWith("<"))) { - array[index++] = methodTable[i]; + array[index++] = new Method(vmClass.methodTable[i]); } } } @@ -482,13 +485,14 @@ public final class Class } public Class[] getInterfaces() { - if (interfaceTable != null) { - avian.SystemClassLoader.link(this); + if (vmClass.interfaceTable != null) { + SystemClassLoader.link(vmClass); int stride = (isInterface() ? 1 : 2); - Class[] array = new Class[interfaceTable.length / stride]; + Class[] array = new Class[vmClass.interfaceTable.length / stride]; for (int i = 0; i < array.length; ++i) { - array[i] = (Class) interfaceTable[i * stride]; + array[i] = SystemClassLoader.getClass + ((VMClass) vmClass.interfaceTable[i * stride]); } return array; } else { @@ -509,36 +513,41 @@ public final class Class } public ClassLoader getClassLoader() { - return loader; + return vmClass.loader; } public int getModifiers() { - return flags; + return vmClass.flags; } public boolean isInterface() { - return (flags & Modifier.INTERFACE) != 0; + return (vmClass.flags & Modifier.INTERFACE) != 0; } public Class getSuperclass() { - return super_; + return SystemClassLoader.getClass(vmClass.super_); } public boolean isArray() { - return arrayDimensions != 0; + return vmClass.arrayDimensions != 0; + } + + public static boolean isInstance(VMClass c, Object o) { + return o != null && isAssignableFrom(c, SystemClassLoader.getVMClass(o)); } public boolean isInstance(Object o) { - return o != null && isAssignableFrom(o.getClass()); + return isInstance(vmClass, o); } public boolean isPrimitive() { - return (vmFlags & PrimitiveFlag) != 0; + return (vmClass.vmFlags & PrimitiveFlag) != 0; } public URL getResource(String path) { if (! path.startsWith("/")) { - String name = new String(this.name, 0, this.name.length - 1, false); + String name = new String + (vmClass.name, 0, vmClass.name.length - 1, false); int index = name.lastIndexOf('/'); if (index >= 0) { path = name.substring(0, index) + "/" + path; @@ -573,11 +582,11 @@ public final class Class } public Object[] getSigners() { - return addendum == null ? null : addendum.signers; + return vmClass.addendum.signers; } public Package getPackage() { - if ((vmFlags & PrimitiveFlag) != 0 || isArray()) { + if ((vmClass.vmFlags & PrimitiveFlag) != 0 || isArray()) { return null; } else { String name = getCanonicalName(); @@ -597,25 +606,25 @@ public final class Class return getAnnotation(class_) != null; } - private Annotation getAnnotation(Object[] a) { + private static Annotation getAnnotation(VMClass c, Object[] a) { if (a[0] == null) { a[0] = Proxy.newProxyInstance - (loader, new Class[] { (Class) a[1] }, + (c.loader, new Class[] { (Class) a[1] }, new AnnotationInvocationHandler(a)); } return (Annotation) a[0]; } public T getAnnotation(Class class_) { - for (Class c = this; c != null; c = c.super_) { + for (VMClass c = vmClass; c != null; c = c.super_) { if (c.addendum != null && c.addendum.annotationTable != null) { - avian.SystemClassLoader.link(c, c.loader); + SystemClassLoader.link(c, c.loader); Object[] table = (Object[]) c.addendum.annotationTable; for (int i = 0; i < table.length; ++i) { Object[] a = (Object[]) table[i]; if (a[1] == class_) { - return (T) c.getAnnotation(a); + return (T) getAnnotation(c, a); } } } @@ -624,13 +633,13 @@ public final class Class } public Annotation[] getDeclaredAnnotations() { - if (addendum != null && addendum.annotationTable != null) { - avian.SystemClassLoader.link(this); + if (vmClass.addendum.annotationTable != null) { + SystemClassLoader.link(vmClass); - Object[] table = (Object[]) addendum.annotationTable; + Object[] table = (Object[]) vmClass.addendum.annotationTable; Annotation[] array = new Annotation[table.length]; for (int i = 0; i < table.length; ++i) { - array[i] = getAnnotation((Object[]) table[i]); + array[i] = getAnnotation(vmClass, (Object[]) table[i]); } return array; } else { @@ -640,7 +649,7 @@ public final class Class private int countAnnotations() { int count = 0; - for (Class c = this; c != null; c = c.super_) { + for (VMClass c = vmClass; c != null; c = c.super_) { if (c.addendum != null && c.addendum.annotationTable != null) { count += ((Object[]) c.addendum.annotationTable).length; } @@ -651,11 +660,11 @@ public final class Class public Annotation[] getAnnotations() { Annotation[] array = new Annotation[countMethods(true)]; int i = 0; - for (Class c = this; c != null; c = c.super_) { + for (VMClass c = vmClass; c != null; c = c.super_) { if (c.addendum != null && c.addendum.annotationTable != null) { Object[] table = (Object[]) c.addendum.annotationTable; for (int j = 0; j < table.length; ++j) { - array[i++] = getAnnotation((Object[]) table[j]); + array[i++] = getAnnotation(vmClass, (Object[]) table[j]); } } } @@ -692,14 +701,4 @@ public final class Class p.add(new AllPermission()); return new ProtectionDomain(null, p); } - - // for GNU Classpath compatibility: - void setSigners(Object[] signers) { - if (signers != null && signers.length > 0) { - if (addendum == null) { - addendum = new avian.ClassAddendum(); - } - addendum.signers = signers; - } - } } diff --git a/classpath/java/lang/ClassLoader.java b/classpath/java/lang/ClassLoader.java index 3cc052ac48..c63d971440 100644 --- a/classpath/java/lang/ClassLoader.java +++ b/classpath/java/lang/ClassLoader.java @@ -46,7 +46,8 @@ public abstract class ClassLoader { throw new IndexOutOfBoundsException(); } - return avian.SystemClassLoader.defineClass(this, b, offset, length); + return avian.SystemClassLoader.getClass + (avian.SystemClassLoader.defineVMClass(this, b, offset, length)); } protected Class findClass(String name) throws ClassNotFoundException { @@ -87,7 +88,7 @@ public abstract class ClassLoader { } protected void resolveClass(Class c) { - avian.SystemClassLoader.link(c, this); + avian.SystemClassLoader.link(c.vmClass, this); } private ClassLoader getParent() { diff --git a/classpath/java/lang/Object.java b/classpath/java/lang/Object.java index bfd2da9eea..24e6d2dd4b 100644 --- a/classpath/java/lang/Object.java +++ b/classpath/java/lang/Object.java @@ -27,7 +27,11 @@ public class Object { protected void finalize() throws Throwable { } - public native final Class getClass(); + public final Class getClass() { + return avian.SystemClassLoader.getClass(getVMClass(this)); + } + + private static native avian.VMClass getVMClass(Object o); public native int hashCode(); diff --git a/classpath/java/lang/reflect/Constructor.java b/classpath/java/lang/reflect/Constructor.java index ac42178373..324797fe9a 100644 --- a/classpath/java/lang/reflect/Constructor.java +++ b/classpath/java/lang/reflect/Constructor.java @@ -78,13 +78,13 @@ public class Constructor extends AccessibleObject return method.getGenericParameterTypes(); } - private static native T make(Class c); + private static native Object make(avian.VMClass c); public T newInstance(Object ... arguments) throws InvocationTargetException, InstantiationException, IllegalAccessException { - T v = make(method.getDeclaringClass()); + T v = (T) make(method.getDeclaringClass().vmClass); method.invoke(v, arguments); return v; } diff --git a/classpath/java/lang/reflect/Field.java b/classpath/java/lang/reflect/Field.java index 0d015b8254..504b85d402 100644 --- a/classpath/java/lang/reflect/Field.java +++ b/classpath/java/lang/reflect/Field.java @@ -10,7 +10,9 @@ package java.lang.reflect; +import avian.VMField; import avian.AnnotationInvocationHandler; +import avian.SystemClassLoader; import java.lang.annotation.Annotation; @@ -26,81 +28,90 @@ public class Field extends AccessibleObject { private static final int BooleanField = 8; private static final int ObjectField = 9; - private byte vmFlags; - private byte code; - private short flags; - private short offset; - private byte[] name; - public byte[] spec; - public avian.Addendum addendum; - private Class class_; + private final VMField vmField; + private boolean accessible = true; - private Field() { } + public Field(VMField vmField) { + this.vmField = vmField; + } public boolean isAccessible() { - return (vmFlags & Accessible) != 0; + return accessible; } public void setAccessible(boolean v) { - if (v) vmFlags |= Accessible; else vmFlags &= ~Accessible; + accessible = v; } public Class getDeclaringClass() { - return class_; + return SystemClassLoader.getClass(vmField.class_); } public int getModifiers() { - return flags; + return vmField.flags; } public String getName() { - return new String(name, 0, name.length - 1, false); + return getName(vmField); + } + + public static String getName(VMField vmField) { + return new String(vmField.name, 0, vmField.name.length - 1, false); } public Class getType() { - return Class.forCanonicalName(class_.getClassLoader(), - new String(spec, 0, spec.length - 1, false)); + return Class.forCanonicalName + (vmField.class_.loader, + new String(vmField.spec, 0, vmField.spec.length - 1, false)); } public Object get(Object instance) throws IllegalAccessException { Object target; - if ((flags & Modifier.STATIC) != 0) { - target = class_.staticTable(); - } else if (class_.isInstance(instance)) { + if ((vmField.flags & Modifier.STATIC) != 0) { + target = vmField.class_.staticTable; + } else if (Class.isInstance(vmField.class_, instance)) { target = instance; } else { throw new IllegalArgumentException(); } - switch (code) { + switch (vmField.code) { case ByteField: - return Byte.valueOf((byte) getPrimitive(target, code, offset)); + return Byte.valueOf + ((byte) getPrimitive(target, vmField.code, vmField.offset)); case BooleanField: - return Boolean.valueOf(getPrimitive(target, code, offset) != 0); + return Boolean.valueOf + (getPrimitive(target, vmField.code, vmField.offset) != 0); case CharField: - return Character.valueOf((char) getPrimitive(target, code, offset)); + return Character.valueOf + ((char) getPrimitive(target, vmField.code, vmField.offset)); case ShortField: - return Short.valueOf((short) getPrimitive(target, code, offset)); + return Short.valueOf + ((short) getPrimitive(target, vmField.code, vmField.offset)); case IntField: - return Integer.valueOf((int) getPrimitive(target, code, offset)); + return Integer.valueOf + ((int) getPrimitive(target, vmField.code, vmField.offset)); case LongField: - return Long.valueOf((int) getPrimitive(target, code, offset)); + return Long.valueOf + ((int) getPrimitive(target, vmField.code, vmField.offset)); case FloatField: return Float.valueOf - (Float.intBitsToFloat((int) getPrimitive(target, code, offset))); + (Float.intBitsToFloat + ((int) getPrimitive(target, vmField.code, vmField.offset))); case DoubleField: return Double.valueOf - (Double.longBitsToDouble(getPrimitive(target, code, offset))); + (Double.longBitsToDouble + (getPrimitive(target, vmField.code, vmField.offset))); case ObjectField: - return getObject(target, offset); + return getObject(target, vmField.offset); default: throw new Error(); @@ -143,56 +154,58 @@ public class Field extends AccessibleObject { throws IllegalAccessException { Object target; - if ((flags & Modifier.STATIC) != 0) { - target = class_.staticTable(); - } else if (class_.isInstance(instance)) { + if ((vmField.flags & Modifier.STATIC) != 0) { + target = vmField.class_.staticTable; + } else if (Class.isInstance(vmField.class_, instance)) { target = instance; } else { throw new IllegalArgumentException(); } - switch (code) { + switch (vmField.code) { case ByteField: - setPrimitive(target, code, offset, (Byte) value); + setPrimitive(target, vmField.code, vmField.offset, (Byte) value); break; case BooleanField: - setPrimitive(target, code, offset, ((Boolean) value) ? 1 : 0); + setPrimitive + (target, vmField.code, vmField.offset, ((Boolean) value) ? 1 : 0); break; case CharField: - setPrimitive(target, code, offset, (Character) value); + setPrimitive(target, vmField.code, vmField.offset, (Character) value); break; case ShortField: - setPrimitive(target, code, offset, (Short) value); + setPrimitive(target, vmField.code, vmField.offset, (Short) value); break; case IntField: - setPrimitive(target, code, offset, (Integer) value); + setPrimitive(target, vmField.code, vmField.offset, (Integer) value); break; case LongField: - setPrimitive(target, code, offset, (Long) value); + setPrimitive(target, vmField.code, vmField.offset, (Long) value); break; case FloatField: - setPrimitive(target, code, offset, + setPrimitive(target, vmField.code, vmField.offset, Float.floatToRawIntBits((Float) value)); break; case DoubleField: - setPrimitive(target, code, offset, + setPrimitive(target, vmField.code, vmField.offset, Double.doubleToRawLongBits((Double) value)); break; case ObjectField: if (value == null || getType().isInstance(value)) { - setObject(target, offset, value); + setObject(target, vmField.offset, value); } else { throw new IllegalArgumentException - ("needed " + getType() + ", got " + value.getClass().getName() + - " when setting " + class_.getName() + "." + getName()); + ("needed " + getType() + ", got " + + Class.getName(Class.vmClass(target)) + + " when setting " + Class.getName(vmField.class_) + "." + getName()); } break; @@ -204,15 +217,15 @@ public class Field extends AccessibleObject { private Annotation getAnnotation(Object[] a) { if (a[0] == null) { a[0] = Proxy.newProxyInstance - (class_.getClassLoader(), new Class[] { (Class) a[1] }, + (vmField.class_.loader, new Class[] { (Class) a[1] }, new AnnotationInvocationHandler(a)); } return (Annotation) a[0]; } public T getAnnotation(Class class_) { - if (addendum != null && addendum.annotationTable != null) { - Object[] table = (Object[]) addendum.annotationTable; + if (vmField.addendum.annotationTable != null) { + Object[] table = (Object[]) vmField.addendum.annotationTable; for (int i = 0; i < table.length; ++i) { Object[] a = (Object[]) table[i]; if (a[1] == class_) { @@ -224,8 +237,8 @@ public class Field extends AccessibleObject { } public Annotation[] getAnnotations() { - if (addendum != null && addendum.annotationTable != null) { - Object[] table = (Object[]) addendum.annotationTable; + if (vmField.addendum.annotationTable != null) { + Object[] table = (Object[]) vmField.addendum.annotationTable; Annotation[] array = new Annotation[table.length]; for (int i = 0; i < table.length; ++i) { array[i] = getAnnotation((Object[]) table[i]); @@ -255,9 +268,4 @@ public class Field extends AccessibleObject { private static native void setObject (Object instance, int offset, Object value); - - public static class Addendum { - public Object pool; - public Object annotationTable; - } } diff --git a/classpath/java/lang/reflect/Method.java b/classpath/java/lang/reflect/Method.java index 8a8e383cfb..2db5698eac 100644 --- a/classpath/java/lang/reflect/Method.java +++ b/classpath/java/lang/reflect/Method.java @@ -10,53 +10,54 @@ package java.lang.reflect; +import avian.VMMethod; import avian.AnnotationInvocationHandler; +import avian.SystemClassLoader; import java.lang.annotation.Annotation; public class Method extends AccessibleObject implements Member, GenericDeclaration { - private byte vmFlags; - private byte returnCode; - public byte parameterCount; - public byte parameterFootprint; - private short flags; - private short offset; - private int nativeID; - private byte[] name; - public byte[] spec; - public avian.Addendum addendum; - private Class class_; - private Object code; - private long compiled; + private final VMMethod vmMethod; + private boolean accessible; - private Method() { } + public Method(VMMethod vmMethod) { + this.vmMethod = vmMethod; + } public boolean isAccessible() { - return (vmFlags & Accessible) != 0; + return accessible; } public void setAccessible(boolean v) { - if (v) vmFlags |= Accessible; else vmFlags &= ~Accessible; + accessible = v; } - public static native Method getCaller(); + public static native VMMethod getCaller(); public Class getDeclaringClass() { - return class_; + return SystemClassLoader.getClass(vmMethod.class_); } public int getModifiers() { - return flags; + return vmMethod.flags; } public String getName() { - return new String(name, 0, name.length - 1, false); + return getName(vmMethod); } - String getSpec() { - return new String(spec, 0, spec.length - 1, false); + public static String getName(VMMethod vmMethod) { + return new String(vmMethod.name, 0, vmMethod.name.length - 1, false); + } + + private String getSpec() { + return getSpec(vmMethod); + } + + public static String getSpec(VMMethod vmMethod) { + return new String(vmMethod.spec, 0, vmMethod.spec.length - 1, false); } private static int next(char c, String s, int start) { @@ -67,12 +68,17 @@ public class Method extends AccessibleObject } public Class[] getParameterTypes() { - int count = parameterCount; + return getParameterTypes(vmMethod); + } + + public static Class[] getParameterTypes(VMMethod vmMethod) { + int count = vmMethod.parameterCount; Class[] types = new Class[count]; int index = 0; - String spec = new String(this.spec, 1, this.spec.length - 1, false); + String spec = new String + (vmMethod.spec, 1, vmMethod.spec.length - 1, false); try { for (int i = 0; i < spec.length(); ++i) { @@ -83,7 +89,7 @@ public class Method extends AccessibleObject int start = i + 1; i = next(';', spec, start); String name = spec.substring(start, i).replace('/', '.'); - types[index++] = Class.forName(name, true, class_.getClassLoader()); + types[index++] = Class.forName(name, true, vmMethod.class_.loader); } else if (c == '[') { int start = i; while (spec.charAt(i) == '[') ++i; @@ -92,16 +98,16 @@ public class Method extends AccessibleObject i = next(';', spec, i + 1); String name = spec.substring(start, i).replace('/', '.'); types[index++] = Class.forName - (name, true, class_.getClassLoader()); + (name, true, vmMethod.class_.loader); } else { String name = spec.substring(start, i + 1); types[index++] = Class.forCanonicalName - (class_.getClassLoader(), name); + (vmMethod.class_.loader, name); } } else { String name = spec.substring(i, i + 1); types[index++] = Class.forCanonicalName - (class_.getClassLoader(), name); + (vmMethod.class_.loader, name); } } } catch (ClassNotFoundException e) { @@ -114,38 +120,43 @@ public class Method extends AccessibleObject public Object invoke(Object instance, Object ... arguments) throws InvocationTargetException, IllegalAccessException { - if ((flags & Modifier.STATIC) != 0 || class_.isInstance(instance)) { - if ((flags & Modifier.STATIC) != 0) { + if ((vmMethod.flags & Modifier.STATIC) != 0 + || Class.isInstance(vmMethod.class_, instance)) + { + if ((vmMethod.flags & Modifier.STATIC) != 0) { instance = null; } if (arguments == null) { - if (parameterCount > 0) { + if (vmMethod.parameterCount > 0) { throw new NullPointerException(); } arguments = new Object[0]; } - if (arguments.length == parameterCount) { - return invoke(this, instance, arguments); + if (arguments.length == vmMethod.parameterCount) { + return invoke(vmMethod, instance, arguments); } else { throw new ArrayIndexOutOfBoundsException(); } } else { +// System.out.println +// (getDeclaringClass() + "." + getName() + " flags: " + vmMethod.flags + " vm flags: " + vmMethod.vmFlags + " return code: " + vmMethod.returnCode); throw new IllegalArgumentException(); } } - private static native Object invoke(Method method, Object instance, + private static native Object invoke(VMMethod method, Object instance, Object ... arguments) throws InvocationTargetException, IllegalAccessException; public Class getReturnType() { - for (int i = 0; i < spec.length - 1; ++i) { - if (spec[i] == ')') { + for (int i = 0; i < vmMethod.spec.length - 1; ++i) { + if (vmMethod.spec[i] == ')') { return Class.forCanonicalName - (class_.getClassLoader(), - new String(spec, i + 1, spec.length - i - 2, false)); + (vmMethod.class_.loader, + new String + (vmMethod.spec, i + 1, vmMethod.spec.length - i - 2, false)); } } throw new RuntimeException(); @@ -154,15 +165,15 @@ public class Method extends AccessibleObject private Annotation getAnnotation(Object[] a) { if (a[0] == null) { a[0] = Proxy.newProxyInstance - (class_.getClassLoader(), new Class[] { (Class) a[1] }, + (vmMethod.class_.loader, new Class[] { (Class) a[1] }, new AnnotationInvocationHandler(a)); } return (Annotation) a[0]; } public T getAnnotation(Class class_) { - if (addendum != null && addendum.annotationTable != null) { - Object[] table = (Object[]) addendum.annotationTable; + if (vmMethod.addendum.annotationTable != null) { + Object[] table = (Object[]) vmMethod.addendum.annotationTable; for (int i = 0; i < table.length; ++i) { Object[] a = (Object[]) table[i]; if (a[1] == class_) { @@ -174,8 +185,8 @@ public class Method extends AccessibleObject } public Annotation[] getAnnotations() { - if (addendum != null && addendum.annotationTable != null) { - Object[] table = (Object[]) addendum.annotationTable; + if (vmMethod.addendum.annotationTable != null) { + Object[] table = (Object[]) vmMethod.addendum.annotationTable; Annotation[] array = new Annotation[table.length]; for (int i = 0; i < table.length; ++i) { array[i] = getAnnotation((Object[]) table[i]); diff --git a/classpath/java/lang/reflect/Proxy.java b/classpath/java/lang/reflect/Proxy.java index aca0351217..15119c8d30 100644 --- a/classpath/java/lang/reflect/Proxy.java +++ b/classpath/java/lang/reflect/Proxy.java @@ -45,12 +45,14 @@ public class Proxy { private static final int getfield = 0xb4; private static final int iload = 0x15; private static final int invokeinterface = 0xb9; + private static final int invokespecial = 0xb7; private static final int invokestatic = 0xb8; private static final int invokevirtual = 0xb6; private static final int ireturn = 0xac; private static final int ldc_w = 0x13; private static final int lload = 0x16; private static final int lreturn = 0xad; + private static final int new_ = 0xbb; private static final int pop = 0x57; private static final int putfield = 0xb5; private static final int return_ = 0xb1; @@ -172,15 +174,26 @@ public class Proxy { write1(out, aload_0); + write1(out, new_); + write2(out, poolAddClass(pool, "java/lang/reflect/Method") + 1); + write1(out, dup); write1(out, ldc_w); write2(out, poolAddClass(pool, className) + 1); write1(out, getfield); write2(out, poolAddFieldRef (pool, "java/lang/Class", - "methodTable", "[Ljava/lang/reflect/Method;") + 1); + "vmClass", "Lavian/VMClass;") + 1); + write1(out, getfield); + write2(out, poolAddFieldRef + (pool, "avian/VMClass", + "methodTable", "[Lavian/VMMethod;") + 1); write1(out, ldc_w); write2(out, poolAddInteger(pool, index) + 1); write1(out, aaload); + write1(out, invokespecial); + write2(out, poolAddMethodRef + (pool, "java/lang/reflect/Method", + "", "(Lavian/VMMethod;)V") + 1); write1(out, ldc_w); write2(out, poolAddInteger(pool, parameterCount) + 1); @@ -434,22 +447,22 @@ public class Proxy { interfaceIndexes[i] = poolAddClass(pool, interfaces[i].getName()); } - Map virtualMap = new HashMap(); + Map virtualMap = new HashMap(); for (Class c: interfaces) { - Method[] ivtable = c.virtualTable; + avian.VMMethod[] ivtable = c.vmClass.virtualTable; if (ivtable != null) { - for (Method m: ivtable) { - virtualMap.put(m.getName() + m.getSpec(), m); + for (avian.VMMethod m: ivtable) { + virtualMap.put(Method.getName(m) + Method.getSpec(m), m); } } } MethodData[] methodTable = new MethodData[virtualMap.size() + 1]; { int i = 0; - for (Method m: virtualMap.values()) { + for (avian.VMMethod m: virtualMap.values()) { methodTable[i] = new MethodData - (poolAddUtf8(pool, m.getName()), - poolAddUtf8(pool, m.getSpec()), + (poolAddUtf8(pool, Method.getName(m)), + poolAddUtf8(pool, Method.getSpec(m)), makeInvokeCode(pool, name, m.spec, m.parameterCount, m.parameterFootprint, i)); ++ i; @@ -501,8 +514,9 @@ public class Proxy { write2(out, 0); // attribute count byte[] classData = out.toByteArray(); - return avian.SystemClassLoader.defineClass - (loader, classData, 0, classData.length); + return avian.SystemClassLoader.getClass + (avian.SystemClassLoader.defineVMClass + (loader, classData, 0, classData.length)); } public static Object newProxyInstance(ClassLoader loader, diff --git a/classpath/java/util/ResourceBundle.java b/classpath/java/util/ResourceBundle.java index 97bde9b80c..4dc52443f6 100644 --- a/classpath/java/util/ResourceBundle.java +++ b/classpath/java/util/ResourceBundle.java @@ -94,13 +94,12 @@ public abstract class ResourceBundle { } public static ResourceBundle getBundle(String name, Locale locale) { - return getBundle(name, locale, - Method.getCaller().getDeclaringClass().getClassLoader()); + return getBundle(name, locale, Method.getCaller().class_.loader); } public static ResourceBundle getBundle(String name) { - return getBundle(name, Locale.getDefault(), - Method.getCaller().getDeclaringClass().getClassLoader()); + return getBundle + (name, Locale.getDefault(), Method.getCaller().class_.loader); } public Object getObject(String key) { diff --git a/classpath/java/util/logging/Logger.java b/classpath/java/util/logging/Logger.java index d06a7bb00a..ed2a8ce4d6 100644 --- a/classpath/java/util/logging/Logger.java +++ b/classpath/java/util/logging/Logger.java @@ -107,15 +107,15 @@ public class Logger { return logger.getLevel(); } - private void log(Level level, Method caller, String message, + private void log(Level level, avian.VMMethod caller, String message, Throwable exception) { if (level.intValue() < getEffectiveLevel().intValue()) { return; } LogRecord r = new LogRecord - (name, caller == null ? "" : caller.getName(), level, message, - exception); + (name, caller == null ? "" : Method.getName(caller), level, + message, exception); publish(r); } diff --git a/src/builtin.cpp b/src/builtin.cpp index d8ee84cc2c..13333a1fb6 100644 --- a/src/builtin.cpp +++ b/src/builtin.cpp @@ -97,12 +97,12 @@ Avian_java_lang_Object_toString } extern "C" JNIEXPORT int64_t JNICALL -Avian_java_lang_Object_getClass +Avian_java_lang_Object_getVMClass (Thread* t, object, uintptr_t* arguments) { - object this_ = reinterpret_cast(arguments[0]); + object o = reinterpret_cast(arguments[0]); - return reinterpret_cast(objectClass(t, this_)); + return reinterpret_cast(objectClass(t, o)); } extern "C" JNIEXPORT void JNICALL @@ -183,7 +183,15 @@ Avian_avian_SystemClassLoader_releaseClassLock } extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_SystemClassLoader_defineClass +Avian_avian_SystemClassLoader_getVMClass +(Thread* t, object, uintptr_t* arguments) +{ + return reinterpret_cast + (objectClass(t, reinterpret_cast(arguments[0]))); +} + +extern "C" JNIEXPORT int64_t JNICALL +Avian_avian_SystemClassLoader_defineVMClass (Thread* t, object, uintptr_t* arguments) { object loader = reinterpret_cast(arguments[0]); @@ -214,25 +222,25 @@ Avian_avian_SystemClassLoader_defineClass } extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_SystemClassLoader_reallyFindLoadedClass +Avian_avian_SystemClassLoader_findLoadedVMClass (Thread* t, object, uintptr_t* arguments) { - object name = reinterpret_cast(arguments[1]); + object name = reinterpret_cast(arguments[0]); return search(t, name, findLoadedSystemClass, true); } extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_SystemClassLoader_findClass +Avian_avian_SystemClassLoader_findVMClass (Thread* t, object, uintptr_t* arguments) { - object name = reinterpret_cast(arguments[1]); + object name = reinterpret_cast(arguments[0]); return search(t, name, resolveSystemClass, true); } extern "C" JNIEXPORT int64_t JNICALL -Avian_avian_SystemClassLoader_resolveClass +Avian_avian_SystemClassLoader_resolveVMClass (Thread* t, object, uintptr_t* arguments) { object loader = reinterpret_cast(arguments[0]); @@ -245,7 +253,7 @@ extern "C" JNIEXPORT int64_t JNICALL Avian_avian_SystemClassLoader_resourceExists (Thread* t, object, uintptr_t* arguments) { - object name = reinterpret_cast(arguments[1]); + object name = reinterpret_cast(arguments[0]); if (LIKELY(name)) { RUNTIME_ARRAY(char, n, stringLength(t, name) + 1); diff --git a/src/compile.cpp b/src/compile.cpp index e5d7a7df2d..a35fa98905 100644 --- a/src/compile.cpp +++ b/src/compile.cpp @@ -4370,7 +4370,11 @@ compile(MyThread* t, Frame* initialFrame, unsigned ip, object class_ = resolveClassInPool(t, context->method, index - 1); if (UNLIKELY(t->exception)) return; - frame->pushObject(frame->append(class_)); + frame->pushObject(frame->append(getJClass(t, class_))); + } else if (objectClass(t, v) + == arrayBody(t, t->m->types, Machine::ClassType)) + { + frame->pushObject(frame->append(getJClass(t, v))); } else { frame->pushObject(frame->append(v)); } @@ -6160,9 +6164,6 @@ invokeNativeSlow(MyThread* t, object method) { PROTECT(t, method); - object class_ = methodClass(t, method); - PROTECT(t, class_); - unsigned footprint = methodParameterFootprint(t, method) + 1; if (methodFlags(t, method) & ACC_STATIC) { ++ footprint; @@ -6181,9 +6182,13 @@ invokeNativeSlow(MyThread* t, object method) + t->arch->frameFooterSize() + t->arch->frameReturnAddressSize(); + object jclass = 0; + PROTECT(t, jclass); + if (methodFlags(t, method) & ACC_STATIC) { + jclass = getJClass(t, methodClass(t, method)); RUNTIME_ARRAY_BODY(args)[argOffset++] - = reinterpret_cast(&class_); + = reinterpret_cast(&jclass); } else { RUNTIME_ARRAY_BODY(args)[argOffset++] = reinterpret_cast(sp++); diff --git a/src/interpret.cpp b/src/interpret.cpp index e63613cb54..28754a0a3b 100644 --- a/src/interpret.cpp +++ b/src/interpret.cpp @@ -2224,7 +2224,11 @@ interpret(Thread* t) (t, frameMethod(t, frame), index - 1); if (UNLIKELY(exception)) goto throw_; - pushObject(t, class_); + pushObject(t, getJClass(t, class_)); + } else if (objectClass(t, v) + == arrayBody(t, t->m->types, Machine::ClassType)) + { + pushObject(t, getJClass(t, v)); } else { pushObject(t, v); } diff --git a/src/jnienv.cpp b/src/jnienv.cpp index 4404014ef9..a7b7b0cb6f 100644 --- a/src/jnienv.cpp +++ b/src/jnienv.cpp @@ -248,7 +248,9 @@ FindClass(Thread* t, const char* name) object n = makeByteArray(t, strlen(name) + 1); replace('.', '/', name, &byteArrayBody(t, n, 0)); - return makeLocalReference(t, resolveClass(t, t->m->loader, n)); + object c = resolveClass(t, t->m->loader, n); + + return makeLocalReference(t, c == 0 ? 0 : getJClass(t, c)); } jint JNICALL @@ -270,7 +272,7 @@ ThrowNew(Thread* t, jclass c, const char* message) object trace = makeTrace(t); PROTECT(t, trace); - t->exception = make(t, *c); + t->exception = make(t, jclassVmClass(t, *c)); set(t, t->exception, ThrowableMessage, m); set(t, t->exception, ThrowableTrace, trace); @@ -316,7 +318,7 @@ GetObjectClass(Thread* t, jobject o) { ENTER(t, Thread::ActiveState); - return makeLocalReference(t, objectClass(t, *o)); + return makeLocalReference(t, getJClass(t, objectClass(t, *o))); } jboolean JNICALL @@ -324,7 +326,7 @@ IsInstanceOf(Thread* t, jobject o, jclass c) { ENTER(t, Thread::ActiveState); - return instanceOf(t, *c, *o); + return instanceOf(t, jclassVmClass(t, *c), *o); } object @@ -334,7 +336,7 @@ findMethod(Thread* t, jclass c, const char* name, const char* spec) PROTECT(t, n); object s = makeByteArray(t, "%s", spec); - return vm::findMethod(t, *c, n, s); + return vm::findMethod(t, jclassVmClass(t, *c), n, s); } jint @@ -395,7 +397,7 @@ NewObjectV(Thread* t, jclass c, jmethodID m, va_list a) { ENTER(t, Thread::ActiveState); - object o = make(t, *c); + object o = make(t, jclassVmClass(t, *c)); PROTECT(t, o); t->m->processor->invokeList(t, getMethod(t, m), o, true, a); @@ -875,7 +877,7 @@ GetFieldID(Thread* t, jclass c, const char* name, const char* spec) { ENTER(t, Thread::ActiveState); - object field = resolveField(t, *c, name, spec); + object field = resolveField(t, jclassVmClass(t, *c), name, spec); if (UNLIKELY(t->exception)) return 0; return fieldOffset(t, field); @@ -886,7 +888,7 @@ GetStaticFieldID(Thread* t, jclass c, const char* name, const char* spec) { ENTER(t, Thread::ActiveState); - object field = resolveField(t, *c, name, spec); + object field = resolveField(t, jclassVmClass(t, *c), name, spec); if (UNLIKELY(t->exception)) return 0; return fieldOffset(t, field); @@ -1041,7 +1043,8 @@ GetStaticObjectField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return makeLocalReference(t, cast(classStaticTable(t, *c), field)); + return makeLocalReference + (t, cast(classStaticTable(t, jclassVmClass(t, *c)), field)); } jboolean JNICALL @@ -1049,7 +1052,7 @@ GetStaticBooleanField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return cast(classStaticTable(t, *c), field); + return cast(classStaticTable(t, jclassVmClass(t, *c)), field); } jbyte JNICALL @@ -1057,7 +1060,7 @@ GetStaticByteField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return cast(classStaticTable(t, *c), field); + return cast(classStaticTable(t, jclassVmClass(t, *c)), field); } jchar JNICALL @@ -1065,7 +1068,7 @@ GetStaticCharField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return cast(classStaticTable(t, *c), field); + return cast(classStaticTable(t, jclassVmClass(t, *c)), field); } jshort JNICALL @@ -1073,7 +1076,7 @@ GetStaticShortField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return cast(classStaticTable(t, *c), field); + return cast(classStaticTable(t, jclassVmClass(t, *c)), field); } jint JNICALL @@ -1081,7 +1084,7 @@ GetStaticIntField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return cast(classStaticTable(t, *c), field); + return cast(classStaticTable(t, jclassVmClass(t, *c)), field); } jlong JNICALL @@ -1089,7 +1092,7 @@ GetStaticLongField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return cast(classStaticTable(t, *c), field); + return cast(classStaticTable(t, jclassVmClass(t, *c)), field); } jfloat JNICALL @@ -1097,7 +1100,7 @@ GetStaticFloatField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return cast(classStaticTable(t, *c), field); + return cast(classStaticTable(t, jclassVmClass(t, *c)), field); } jdouble JNICALL @@ -1105,7 +1108,7 @@ GetStaticDoubleField(Thread* t, jclass c, jfieldID field) { ENTER(t, Thread::ActiveState); - return cast(classStaticTable(t, *c), field); + return cast(classStaticTable(t, jclassVmClass(t, *c)), field); } void JNICALL @@ -1121,7 +1124,7 @@ SetStaticBooleanField(Thread* t, jclass c, jfieldID field, jboolean v) { ENTER(t, Thread::ActiveState); - cast(classStaticTable(t, *c), field) = v; + cast(classStaticTable(t, jclassVmClass(t, *c)), field) = v; } void JNICALL @@ -1129,7 +1132,7 @@ SetStaticByteField(Thread* t, jclass c, jfieldID field, jbyte v) { ENTER(t, Thread::ActiveState); - cast(classStaticTable(t, *c), field) = v; + cast(classStaticTable(t, jclassVmClass(t, *c)), field) = v; } void JNICALL @@ -1137,7 +1140,7 @@ SetStaticCharField(Thread* t, jclass c, jfieldID field, jchar v) { ENTER(t, Thread::ActiveState); - cast(classStaticTable(t, *c), field) = v; + cast(classStaticTable(t, jclassVmClass(t, *c)), field) = v; } void JNICALL @@ -1145,7 +1148,7 @@ SetStaticShortField(Thread* t, jclass c, jfieldID field, jshort v) { ENTER(t, Thread::ActiveState); - cast(classStaticTable(t, *c), field) = v; + cast(classStaticTable(t, jclassVmClass(t, *c)), field) = v; } void JNICALL @@ -1153,7 +1156,7 @@ SetStaticIntField(Thread* t, jclass c, jfieldID field, jint v) { ENTER(t, Thread::ActiveState); - cast(classStaticTable(t, *c), field) = v; + cast(classStaticTable(t, jclassVmClass(t, *c)), field) = v; } void JNICALL @@ -1161,7 +1164,7 @@ SetStaticLongField(Thread* t, jclass c, jfieldID field, jlong v) { ENTER(t, Thread::ActiveState); - cast(classStaticTable(t, *c), field) = v; + cast(classStaticTable(t, jclassVmClass(t, *c)), field) = v; } void JNICALL @@ -1169,7 +1172,7 @@ SetStaticFloatField(Thread* t, jclass c, jfieldID field, jfloat v) { ENTER(t, Thread::ActiveState); - cast(classStaticTable(t, *c), field) = v; + cast(classStaticTable(t, jclassVmClass(t, *c)), field) = v; } void JNICALL @@ -1177,7 +1180,7 @@ SetStaticDoubleField(Thread* t, jclass c, jfieldID field, jdouble v) { ENTER(t, Thread::ActiveState); - cast(classStaticTable(t, *c), field) = v; + cast(classStaticTable(t, jclassVmClass(t, *c)), field) = v; } jobject JNICALL @@ -1248,7 +1251,9 @@ NewObjectArray(Thread* t, jsize length, jclass class_, jobject init) { ENTER(t, Thread::ActiveState); - object a = makeObjectArray(t, classLoader(t, *class_), *class_, length); + object a = makeObjectArray + (t, classLoader(t, jclassVmClass(t, *class_)), jclassVmClass(t, *class_), + length); object value = (init ? *init : 0); for (jsize i = 0; i < length; ++i) { set(t, a, ArrayBody + (i * BytesPerWord), value); diff --git a/src/machine.cpp b/src/machine.cpp index 01b766de93..0b4ddcb461 100644 --- a/src/machine.cpp +++ b/src/machine.cpp @@ -1627,7 +1627,7 @@ parseAttributeTable(Thread* t, Stream& s, object class_, object pool) object body = makeByteArray(t, length); s.read(reinterpret_cast(&byteArrayBody(t, body, 0)), length); - object addendum = makeClassAddendum(t, pool, body, 0); + object addendum = makeClassAddendum(t, pool, body, 0, 0); set(t, class_, ClassAddendum, addendum); } else { diff --git a/src/machine.h b/src/machine.h index 4bdfccfc24..b406a455ca 100644 --- a/src/machine.h +++ b/src/machine.h @@ -3000,6 +3000,29 @@ resolveMethod(Thread* t, object method, unsigned index) (t, classLoader(t, methodClass(t, method)), method, index); } +inline object +getJClass(Thread* t, object c) +{ + if (classAddendum(t, c) == 0) { + ACQUIRE(t, t->m->classLock); + + object addendum = makeClassAddendum(t, 0, 0, 0, 0); + + set(t, c, ClassAddendum, addendum); + } + + object jclass = classAddendumClass(t, classAddendum(t, c)); + if (jclass == 0) { + ACQUIRE(t, t->m->classLock); + + jclass = makeJclass(t, c); + + set(t, classAddendum(t, c), ClassAddendumClass, jclass); + } + + return jclass; +} + void dumpHeap(Thread* t, FILE* out); diff --git a/src/types.def b/src/types.def index 184df800a0..143252e352 100644 --- a/src/types.def +++ b/src/types.def @@ -1,8 +1,10 @@ (type jobject java/lang/Object) -(type class java/lang/Class +(type class avian/VMClass (array void* vtable)) +(type jclass java/lang/Class) + (type singleton (array uintptr_t body)) @@ -11,13 +13,10 @@ (type systemClassLoader avian/SystemClassLoader) -(type accessibleObject java/lang/reflect/AccessibleObject) +(type field avian/VMField) -(type field java/lang/reflect/Field) - -(type method java/lang/reflect/Method) - -(type proxy java/lang/reflect/Proxy) +(type method avian/VMMethod + (intptr_t compiled)) (type addendum avian/Addendum)